请选择 进入手机版 | 继续访问电脑版

Java面试题

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2738|回复: 0

分布式唯一ID生成器Twitter 的 Snowflake idworker java版本

[复制链接]

1

主题

1

帖子

15

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
15
发表于 2019-3-25 12:55:03 | 显示全部楼层 |阅读模式
使用方式:
  1. IdWorker idWorker = IdWorker.getMachingNameInstance();
  2.         // System.out.println(Long.toBinaryString(idWorker.nextId()));
  3.         System.out.println(idWorker.nextId());
  4.         System.out.println(idWorker.nextId());
复制代码
代码块

  1. import cn.hutool.log.Log;
  2. import cn.hutool.log.LogFactory;

  3. import java.net.InetAddress;
  4. import java.net.UnknownHostException;
  5. import java.util.regex.Matcher;
  6. import java.util.regex.Pattern;

  7. public class IdWorker {

  8.     private final static Log logger = LogFactory.get();

  9.     private final long workerId;
  10.     private final long epoch = 1403854494756L;   // 时间起始标记点,作为基准,一般取系统的最近时间
  11.     private final long workerIdBits = 10L;      // 机器标识位数
  12.     private final long maxWorkerId = -1L ^ -1L << this.workerIdBits;// 机器ID最大值: 1023
  13.     private long sequence = 0L;                   // 0,并发控制
  14.     private final long sequenceBits = 12L;      //毫秒内自增位
  15.     private static Pattern p = Pattern.compile("[0-9]+");
  16.     private final long workerIdShift = this.sequenceBits;                             // 12
  17.     private final long timestampLeftShift = this.sequenceBits + this.workerIdBits;// 22
  18.     private final long sequenceMask = -1L ^ -1L << this.sequenceBits;                 // 4095,111111111111,12位
  19.     private long lastTimestamp = -1L;

  20.     private IdWorker(long workerId) {
  21.         if (workerId > this.maxWorkerId || workerId < 0) {
  22.             throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", this.maxWorkerId));
  23.         }
  24.         this.workerId = workerId;
  25.     }

  26.     public synchronized long nextId() throws Exception {
  27.         long timestamp = this.timeGen();
  28.         if (this.lastTimestamp == timestamp) { // 如果上一个timestamp与新产生的相等,则sequence加一(0-4095循环); 对新的timestamp,sequence从0开始
  29.             this.sequence = this.sequence + 1 & this.sequenceMask;
  30.             if (this.sequence == 0) {
  31.                 timestamp = this.tilNextMillis(this.lastTimestamp);// 重新生成timestamp
  32.             }
  33.         } else {
  34.             this.sequence = 0;
  35.         }

  36.         if (timestamp < this.lastTimestamp) {
  37.             logger.error(String.format("clock moved backwards.Refusing to generate id for %d milliseconds", (this.lastTimestamp - timestamp)));
  38.             throw new Exception(String.format("clock moved backwards.Refusing to generate id for %d milliseconds", (this.lastTimestamp - timestamp)));
  39.         }

  40.         this.lastTimestamp = timestamp;
  41.         return timestamp - this.epoch << this.timestampLeftShift | this.workerId << this.workerIdShift | this.sequence;
  42.     }

  43.     private static IdWorker flowIdWorker = new IdWorker(1);

  44.     public static IdWorker getFlowIdWorkerInstance() {
  45.         return flowIdWorker;
  46.     }

  47.     /*解析机器名称数字,进行机器编号初始化,特别适合和spark结合的大数据场景
  48.      * */
  49.     public static IdWorker getMachingNameInstance() {
  50.         String machineId = "1";
  51.         try {
  52.             String machine = InetAddress.getLocalHost().getHostName();
  53.             Matcher m = p.matcher(machine);
  54.             while (m.find()) {
  55.                 machineId = m.group(0);
  56.                 logger.info(String.format("idworker id is %s", machineId));
  57.                 break;
  58.             }
  59.         } catch (UnknownHostException e) {
  60.             logger.error(e.getMessage(), e);
  61.         }
  62.         return new IdWorker(Integer.parseInt(machineId));
  63.     }


  64.     /**
  65.      * 等待下一个毫秒的到来, 保证返回的毫秒数在参数lastTimestamp之后
  66.      */
  67.     private long tilNextMillis(long lastTimestamp) {
  68.         long timestamp = this.timeGen();
  69.         while (timestamp <= lastTimestamp) {
  70.             timestamp = this.timeGen();
  71.         }
  72.         return timestamp;
  73.     }

  74.     /**
  75.      * 获得系统当前毫秒数
  76.      */
  77.     private static long timeGen() {
  78.         return System.currentTimeMillis();
  79.     }

  80. }
复制代码


回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|Java面试题

GMT+8, 2019-4-21 04:58 , Processed in 0.061656 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表