栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

分布式雪花算法生成唯一ID

分布式雪花算法生成唯一ID

雪花算法组成

10bit工作进程位:用来记录工作机器的id,包括5位datacenterId和5位workerId;5位(bit)可以表示的最大正整数是31,即可以用0,1,2,3,…31这32个数字,来表示不同的datacenterId和workerId

Hutool工具包


    cn.hutool
    hutool-all
    5.7.16

Snowflake需自行保证单例,否则多个对象生成ID会导致重复

代码

package com.lyods.base.utils;

import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.net.NetUtil;
import cn.hutool.core.util.IdUtil;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class SnowFlakeUtil {

    private final static Logger log = LoggerFactory.getLogger(SnowFlakeUtil.class);

    private static long workerId = 0;

    private volatile static Snowflake snowflake = null;
    private volatile static SnowFlakeUtil sfu = null;

    
    private SnowFlakeUtil() {
    }

    public static SnowFlakeUtil getInstance() {
        if (null == sfu) {
            synchronized (SnowFlakeUtil.class) {
                if (null == sfu) {
                    sfu = new SnowFlakeUtil();
                }
            }
        }
        return sfu;
    }

    
    public long snowflakeId() {
        if (null == snowflake) {
            snowflake = getSnowflake();
        }
        return snowflake.nextId();
    }

    
    public long snowflakeId(long workerId, long dataCenterId) {
        if (null == snowflake) {
            snowflake = getSnowflake(workerId, dataCenterId);
        }
        return snowflake.nextId();
    }

    
    private synchronized Snowflake getSnowflake(long workerId, long dataCenterId) {
        snowflake = IdUtil.getSnowflake(workerId, dataCenterId);
        return snowflake;
    }

    
    private synchronized Snowflake getSnowflake() {
        snowflake = new Snowflake();
        return snowflake;
    }

    @PostConstruct
    public void init() {
        try {
            workerId = NetUtil.ipv4ToLong(NetUtil.getLocalhostStr());
            log.info("当前机器的workId: {}", workerId);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("当前机器的workId获取失败", e);
            workerId = NetUtil.getLocalhostStr().hashCode();
        }
    }

}

线程池30线程测试

ExecutorService executorService = Executors.newFixedThreadPool(5);
Stream.iterate(0, x -> x + 1).limit(30).forEach(x -> {
    executorService.submit(() -> {
        long id = SnowFlakeUtil.getInstance().snowflakeId();
        System.out.println(id);
    });
});

结果

  • 优点
    时间戳位在高位,ID趋势递增(几千页的分页下可以根据最后一条数据ID进行分页提高效率),生成ID性能高,不依赖第三方系统,分布式系统内不会产生ID碰撞(由datacenter和workerId作区分)
  • 缺点
    回拨本机时间可能导致时间戳相同,ID重复,分布式下不同机器可能时间不完全同步
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/585180.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号