ITPub博客

首页 > 应用开发 > Java > Snowflake

Snowflake

原创 Java 作者:壹頁書 时间:2016-06-12 14:31:23 0 删除 编辑

Snowflake算法核心

把时间戳,工作机器id,序列号组合在一起。


除了最高位bit标记为不可用以外,其余三组bit占位均可浮动,看具体的业务需求而定。
默认情况下41bit的时间戳可以支持该算法使用到2082年,10bit的工作机器id可以支持1023台机器,序列号支持1毫秒产生4095个自增序列id。

  1. public class IdWorker {  
  2.   
  3.     private final long twepoch = 1288834974657L;  
  4.     private final long workerIdBits = 5L;  
  5.     private final long datacenterIdBits = 5L;  
  6.     private final long maxWorkerId = -1L ^ (-1L << workerIdBits);  
  7.     private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);  
  8.     private final long sequenceBits = 12L;  
  9.     private final long workerIdShift = sequenceBits;  
  10.     private final long datacenterIdShift = sequenceBits + workerIdBits;  
  11.     private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;  
  12.     private final long sequenceMask = -1L ^ (-1L << sequenceBits);  
  13.   
  14.     private long workerId;  
  15.     private long datacenterId;  
  16.     private long sequence = 0L;  
  17.     private long lastTimestamp = -1L;  
  18.   
  19.     public IdWorker(long workerId, long datacenterId) {  
  20.         if (workerId > maxWorkerId || workerId < 0) {  
  21.             throw new IllegalArgumentException(  
  22.                     String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));  
  23.         }  
  24.         if (datacenterId > maxDatacenterId || datacenterId < 0) {  
  25.             throw new IllegalArgumentException(  
  26.                     String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));  
  27.         }  
  28.         this.workerId = workerId;  
  29.         this.datacenterId = datacenterId;  
  30.     }  
  31.   
  32.     public synchronized long nextId() {  
  33.         long timestamp = timeGen();  
  34.         if (timestamp < lastTimestamp) {  
  35.             throw new RuntimeException(String.format(  
  36.                     "Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));  
  37.         }  
  38.         if (lastTimestamp == timestamp) {  
  39.             sequence = (sequence + 1) & sequenceMask;  
  40.             if (sequence == 0) {  
  41.                 timestamp = tilNextMillis(lastTimestamp);  
  42.             }  
  43.         } else {  
  44.             sequence = 0L;  
  45.         }  
  46.   
  47.         lastTimestamp = timestamp;  
  48.   
  49.         return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift)  
  50.                 | (workerId << workerIdShift) | sequence;  
  51.     }  
  52.   
  53.     protected long tilNextMillis(long lastTimestamp) {  
  54.         long timestamp = timeGen();  
  55.         while (timestamp <= lastTimestamp) {  
  56.             timestamp = timeGen();  
  57.         }  
  58.         return timestamp;  
  59.     }  
  60.   
  61.     protected long timeGen() {  
  62.         return System.currentTimeMillis();  
  63.     }  
  64.   
  65.     public static void main(String[] args) {  
  66.         IdWorker idWorker = new IdWorker(0, 0);  
  67.         for (int i = 0; i < 1000; i++) {  
  68.             long id = idWorker.nextId();  
  69.             System.out.println(id);  
  70.         }  
  71.     }  
  72. }  



原来设计的ID生成方式
http://blog.itpub.net/29254281/viewspace-1811711/

Snowflake有几个缺点
1.对于机器数量有限制
2.服务器时间一旦变更,比如回退时间.可能造成ID冲突
3.对于MySQL来说,应该还是我的那种方式Insert更快.但是没有具体验证.

参考:
http://www.lanindex.com/twitter-snowflake%EF%BC%8C64%E4%BD%8D%E8%87%AA%E5%A2%9Eid%E7%AE%97%E6%B3%95%E8%AF%A6%E8%A7%A3/

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29254281/viewspace-2118973/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: 参加Gdevops总结
请登录后发表评论 登录
全部评论

注册时间:2013-10-19

  • 博文量
    620
  • 访问量
    6339946