<返回更多

twitter snowflake 算法(分布式 id 生成算法)

2022-08-20    梦幻随风
加入收藏

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());}}
声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>