雪花算法生成分布式ID(java)

/**

  • 雪花算法生成分布式ID

  • /// 共64位 第1位不使用,242位为时间戳,4352位为工作机器id,53~64 位为序列号

  • /// 可部署1024个节点,每毫秒可产生4096个唯一id

  • 参考链接:https://blog.csdn.net/yangding_/article/details/52768906
    */
    public class IdWorker {

    /// 工作进程id 5位
    private long workerId;
    /// 数据中心id 5位
    private long datacenterId;
    /// 顺序 12位,0~4095
    private long sequence = 0L;
    // 初始时间戳
    // 1288834974657 是 (Thu, 04 Nov 2010 01:42:54 GMT) 这一时刻到1970-01-01 00:00:00时刻所经过的毫秒数。
    // 41位字节作为时间戳数值的话,大约68年就会用完,
    // 假如你2010年1月1日开始开发系统,如果不减去2010年1月1日的时间戳,那么白白浪费40年的时间戳啊!
    // 所以减去twepoch 可以让系统在41位字节作为时间戳的情况下的运行时间更长。1288834974657L可能就是该项目开始成立的时间。
    private long twepoch = 1288834974657L;
    //长度定义及最大值定义
    private long workerIdBits = 5L;
    private long datacenterIdBits = 5L;
    private long maxWorkerId = -1L ^ (-1L << workerIdBits);
    private long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    private long sequenceBits = 12L;

    // 工作id 左移12位
    private long workerIdShift = sequenceBits;
    //数据中心id 左移17位
    private long datacenterIdShift = sequenceBits + workerIdBits;
    //时间戳左移22位
    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    //判断是否已经到达最大序列号
    private long sequenceMask = -1L ^ (-1L << sequenceBits);

    private long lastTimestamp = -1L;

    public IdWorker(long workerId, long datacenterId) {
    // sanity check for workerId
    if (workerId > maxWorkerId || workerId < 0) {
    throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
    }
    if (datacenterId > maxDatacenterId || datacenterId < 0) {
    throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
    }
    this.workerId = workerId;
    this.datacenterId = datacenterId;
    }

    public synchronized long nextId() {
    long timestamp = timeGen();
    //如果当前时间戳<上次时间戳,则是时间回拨情况,抛出异常
    if (timestamp < lastTimestamp) {
    throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
    }
    //如果是在同一毫秒内,则累加序列号
    if (lastTimestamp == timestamp) {
    sequence = (sequence + 1) & sequenceMask;
    //如果达到最大值,则等待下一毫秒,序列号从0 开始
    if (sequence == 0) {
    timestamp = tilNextMillis(lastTimestamp);
    }
    } else {
    sequence = 0L;
    }
    //重置上一次毫秒数
    lastTimestamp = timestamp;
    //返回时间戳+工作节点+序列号
    return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence;
    }

    /// 获取下一毫秒
    protected long tilNextMillis(long lastTimestamp) {
    long timestamp = timeGen();
    while (timestamp <= lastTimestamp) {
    timestamp = timeGen();
    }
    return timestamp;
    }

    /// 获取当前时间戳
    protected long timeGen() {
    return System.currentTimeMillis();
    }
    }

posted @ 2020-08-28 18:07  她的开呀  阅读(2262)  评论(0编辑  收藏  举报