• 雪花算法生成分布式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();
      }
      }

  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    领导满意的高逼格报告,可视化吊打Excel,仅用5步就能教会你
    TTL
    s.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 0)
    VSCode的配置和插件同步到多台电脑
    C 语言编程 — 高级数据类型 — void 类型
    C 语言编程 — 高级数据类型 — 字符串
  • 原文地址:https://www.cnblogs.com/yloved/p/13578966.html
Copyright © 2020-2023  润新知