在高并发场景中,雪花算法是解决ID冲突的神器
什么是雪花算法
一句话概括:
雪花算法是Twitter设计的根据时间戳、机器标识码和序列号生成的唯一长整型数
能解决什么问题
确保在大规模高并发环境中,可以生成持续递增的唯一长整型数
具有哪些特点
-
唯一性
-
持续递增
-
结果为长整型数字
-
不依赖其他系统,无需引入数据库、Redis等系统
-
吞吐量大,12位序列号情况下,每毫秒可生成 4095个ID
实现原理
符号位:仅表示正、负数,0 - 正
,1 - 负
,雪花算法结果都为正
,即符号位都为0
时间戳:系统 毫秒级 时间戳
工作机器ID:大规模集群中,标识唯一机器的机器码标识
序列号:当前时间戳内的递增编号
使用中可能存在的问题
1. 机器时钟回拨可能会导致ID重复,解决办法:
参照
定义一定的回拨允许范围,比如:
5ms
,程序等待5*2ms
,后重新获取时间戳,进行ID生成
2. 在集群环境中可能会受到工作机器ID
大小的影响,生成的ID并非绝对递增
例子:在
1ms
时,dataCenterId = 10;machineId=20
的机器持续递增生成了id1
;在2ms
时,dataCenterId = 1;machineId=2
的机器持续递增生成了id2
,这时虽然id2
在时间上先生成,但是并不能保证id2 > id1
相同的代码生成的id
长度不一致,比较常见的有18位
和19位
原因:代码中的时间戳虽然分配了41位
,并且进行了左移,但是时间戳的十进制大小区别比较大,比如:
十进制1000
,41位二进制表示为:00000000000000000000000000000001111101000
十进制1100000000000
,41位二进制表示为:10000000000011101000110111111100000000000
由此可以看出,时间戳比较临近时,时间戳差值比较小。二进制即时都是41位,表示十进制的大小也是不一样的,雪花算法的64位二进制同理。
如何解决:定制更短雪花算法生成的ID长度,方法:
建议先考虑缩短机器标识码
和序列号
位数。毕竟有些项目,机器少、交易量小。
3. 数据中心,机器id该怎么设置
利用redis自增序列设置ID,机器启动时从redis中拿取一个ID,利用数据库,为每一台机器分配workId,保存ip和workId的关系