0 | 0001100 10100010 10111110 10001001 01011100 00 | 10001 | 1 1001 | 0000 00000000
Twitter在把存储系统从MySQL迁移到Cassandra的过程中由于Cassandra没有顺序ID生成机制,snowflake 算法是 twitter 开源的分布式 id 生成算法,
就是
把一个 64 位的 long 型的 id,
1 个 bit 是不用的,
用其中的 41 bit 作为毫秒数,
用 10 bit 作为工作机器 id,
12 bit 作为序列号。
于是自己开发了一套全局唯一ID生成服务:Snowflake。
1 bit:不用,为啥呢?因为二进制里第一个 bit 为如果是 1,那么都是负数,但是我们生成的 id 都是正数,所以第一个 bit 统一都是 0。
41位的时间序列(精确到毫秒,41位的长度可以使用69年)
10位的机器标识(10位的长度最多支持部署1024个节点)
12位的计数顺序号(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)
最高位是符号位,始终为0。
优点:高性能,低延迟;独立的应用;按时间有序。
缺点:需要独立的开发和部署。
package com.NETtyrpc.test.util;public class IdWorker {private final long workerId;private final static long twepoch = 1288834974657L;private long sequence = 0L;private final static long workerIdBits = 4L;public final static long maxWorkerId = -1L ^ -1L << workerIdBits;private final static long sequenceBits = 10L;private final static long workerIdShift = sequenceBits;private final static long timestampLeftShift = sequenceBits + workerIdBits;public final static long sequenceMask = -1L ^ -1L << sequenceBits;private long lastTimestamp = -1L;public IdWorker(final long workerId) {super();if (workerId > this.maxWorkerId || workerId < 0) {throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", this.maxWorkerId));}this.workerId = workerId;}public synchronized long nextId() {long timestamp = this.timeGen();if (this.lastTimestamp == timestamp) {this.sequence = (this.sequence + 1) & this.sequenceMask;if (this.sequence == 0) {System.out.println("###########" + sequenceMask);timestamp = this.tilNextMillis(this.lastTimestamp);}} else {this.sequence = 0;}if (timestamp < this.lastTimestamp) {try {throw new Exception(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",this.lastTimestamp - timestamp));} catch (Exception e) {e.printStackTrace();}}this.lastTimestamp = timestamp;long nextId = ((timestamp - twepoch << timestampLeftShift)) | (this.workerId << this.workerIdShift)| (this.sequence);System.out.println("timestamp:" + timestamp + ",timestampLeftShift:" + timestampLeftShift + ",nextId:" + nextId+ ",workerId:" + workerId + ",sequence:" + sequence);return nextId;}private long tilNextMillis(final long lastTimestamp) {long timestamp = this.timeGen();while (timestamp <= lastTimestamp) {timestamp = this.timeGen();}return timestamp;}private long timeGen() {return System.currentTimeMillis();}public static void mAIn(String[] args) {IdWorker worker2 = new IdWorker(2);System.out.println(worker2.nextId());}}