醋醋百科网

Good Luck To You!

分布式雪花算法生成唯一id_分布式id 雪花算法

雪花算法(SnowFlake) ,最早是 Twitter 公司在其内部用于分布式环境下生成唯一 ID,最终生成一个唯一long类型,id基本是递增,对于生成索引,存储空间和数据库索引性能有很大优势。

long类型数值总共有64位,二进制表示 正整数(1位)-毫秒时间戳(41位)-6位机器码-16位自增id

1位 总是0表示正整数

41位 毫秒时间戳

6位 机器码,集群中最多的2^6=64台机器

16位 剩余自增序列 2^16=65536位,每毫秒每个实例最多产生这么多位唯一id

备注:一般的算法是10位机器码,机器编码5位+业务编码5位(或者机房编号)

以下是简单生成id代码实现

public class IdGenerator {

    /** 最后的执行时间 **/
    private long last_ms;

    /** 机器码 **/
    private long workId;

    /** 同一毫秒 **/
    private int sequence;

    /** 初始化时间戳 **/
    private static long init_epoch = DateUtil.parseDate("2023-05-13 00:00:00").getTime();

    public IdGenerator(long workerId) {
        if (workerId > 63) {
            throw new IllegalArgumentException("机器码最大64位");
        }
        this.workId = workerId;
        //初始化赋值最后处理时间
        last_ms = System.currentTimeMillis();
    }

    /**
     * 生成id的入口
     */
    public synchronized long generateId() {
        long current = System.currentTimeMillis();
        //时钟回拨,线程休眠,
        if (current < last_ms) {
            //如果回拨时间很长抛出异常
            if (last_ms - current > 30 * 1000) {
                throw new RuntimeException("时钟回拨超过30s");
            }
            //休眠
            ThreadUtil.safeSleep(last_ms - current);
            return generateId();
        }

        if (current > last_ms) {
            last_ms = current;
            sequence = 0;
            return createId(current);
        }

        //如果序列号超过最大值,休眠1ms,再获取id值
        if ( ++sequence > 65535) {
            ThreadUtil.safeSleep(1);
            sequence = 0;
            return generateId();
        }
        return createId(current);
    }

		/**
     * 位运算拼接id
     */
    private long createId(long current) {
        return ((current - init_epoch) << 22)
                |(workId << 16)
                |sequence;
    }

    public static void main(String[] args) {
        IdGenerator idGenerator = new IdGenerator(0);

        //结果
        Set<Long> idSet = new ConcurrentHashSet<>();

        long s = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            long id = idGenerator.generateId();
            if (idSet.contains(id)) {
                System.out.println("存在重复id");
            } else {
                idSet.add(id);
            }
        }
        System.out.println("执行时间" + (System.currentTimeMillis() - s));
        
    }

}

分布式id性能还是非常优秀的,单线程10万id生成100ms内

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言