雪花算法

该博客介绍了雪花算法的实现,这是一种用于生成全局唯一递增ID的算法。64位ID由符号位、41位毫秒时间戳、5位数据中心ID、5位机器节点ID和12位序列号组成。当遇到时钟回拨时,算法能够处理并避免冲突。示例代码展示了如何使用雪花算法生成ID。
摘要由CSDN通过智能技术生成

/**
 * 雪花算法
 *
 * 生成全局唯一递增ID,共64位。0 -- 00000000 00000000 00000000 00000000 00000000 0 -- 00000 -- 00000 -- 000000000000
 * 第一位表示符号,固定为0,41位表示毫秒时间戳,能用69年,5位表示数据中心ID,5位表示机器节点ID,12位表示同一毫秒内的序列号(4095个)
 * @author fengyurong
 * @date 2021-10-27 6:03 PM
 */
public class MySnowflake {


    //基础毫秒级时间戳 2021-01-01 00:00:00
    public static final long BASE_PERIOD = 1609430400000L;

    //序列号掩码
    public static final long SEQUENCE_MASK = -1L ^ (-1L << 12);

    //机器节点偏移
    public static final int WORK_ID_SHIFT = 12;

    //数据中心偏移
    public static final long DATA_CENTER_ID_SHIFT = WORK_ID_SHIFT + 5;

    //毫秒时间戳偏移量
    public static final long TIMESTAMP_SHIFT = DATA_CENTER_ID_SHIFT + 5;

    //机器节点ID
    public int workId;

    //数据中心ID
    public int dataCenterId;

    //同一毫秒内序列号
    public long sequence = 0L;

    //上一次时间戳
    public long lastTimeStamp;


    public MySnowflake(int workId, int dataCenterId) {
        this.workId = workId;
        this.dataCenterId = dataCenterId;
    }

    
    public long genTime() {
        return System.currentTimeMillis();
    }


    public synchronized long nextId() {
        long timeStamp = this.genTime();


        if(timeStamp <= lastTimeStamp) {
            //能接受2秒内的时钟回拨
            if(timeStamp - lastTimeStamp <= 2000) {
                timeStamp = lastTimeStamp;
            } else {
                throw new RuntimeException("发生了时钟回拨");
            }
        }

        if(timeStamp == lastTimeStamp) {
            sequence = (sequence + 1) & SEQUENCE_MASK;
            timeStamp = this.getNextMil(lastTimeStamp);
        } else {
            sequence = 0L;
        }

        lastTimeStamp = timeStamp;
        return ((timeStamp - BASE_PERIOD) << TIMESTAMP_SHIFT) | (workId << WORK_ID_SHIFT) | (dataCenterId << DATA_CENTER_ID_SHIFT) | sequence;
    }


    /**
     * 循环获取下一毫秒
     * @return
     */
    public long getNextMil(long lastTimeStamp) {
        long timeStamp = this.genTime();
        while(timeStamp == lastTimeStamp) {
            timeStamp = this.genTime();
        }
        if (timeStamp < lastTimeStamp) {
            throw new RuntimeException("发生了时钟回拨");
        }
        return timeStamp;
    }

    public static void main(String[] args) {
        MySnowflake snowflake = new MySnowflake(1,2);
        Set<Long> set = new HashSet<>();
        for (int i = 0; i < 100000000; i++) {
            long id = snowflake.nextId();
            if(set.contains(id)) {
                System.out.println(id);
            }else {
                set.add(id);
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值