发号器方案业内有很多种,我们这里列举如下
1.基于UUID 2.数据库自增ID 3.数据库多主模式 4.号段模式获取 5.双Buffer号段获取 6.Redis 7.twitter雪花算法 8.美团的Leaf 9.百度的UidGenerator 10.滴滴的TinyID
但是在实际使用中,基本上除了1、2和3之外,其他的都有一定程度的使用度,但是每种发号器方案都有着他们自己的一些问题。
1.基于UUID
介绍:使用jdk内置的api
优点:使用简单,为jdk内置的唯一id生成器
缺点:
- 数据为字符
-
2.数据库自增ID
介绍:使用数据库的自增id
优点:无序额外开发,使用简单
缺点: 性能不高:瓶颈为DB
-
3.数据库多主模式ID
介绍:采用多主的数据库的自增id,多主之间进行分片切分采用不同步长
优点:解决数据库自增的单点问题,并无需额外开发,使用简单
缺点: 扩容复杂
-
4.号段+DB获取
介绍:每次从DB获取数据,采用每次获取一个范围,获取完再更新DB
优点:对DB压力小
缺点: 处理方式需要单独开发
-
5.双Buffer+DB号段获取
介绍:基于号段获取中未使用完毕时候异步刷新下次号段
优点:解决号段获取中的性能不是很高问题,可以保持较高的性能
缺点: 可靠性不高:数据获取依赖于DB,虽然有号段缓存,但是如果在短时间内没有启动,则还是有问题
超高并发度支持度:对于一些超高并发度情况下,号段的使用还是会存在网络的数据消耗。不过这个可以通过动态调整号段大小解决,但是动态配置号段过长,则号段浪费也是问题
6.Redis
介绍:通过redis的incr命令实现原子自增操作
优点:使用简单
缺点:重复问题:如果采用RDB方式持久化,则宕机后重启会有数据重复问题,这种可采用AOF的同步每次更新,但这种性能较差
重启时长问题:采用RDB有重复这种最基本问题,那么采用AOF,这里宕机后重启时间过长
7.Twitter的雪花算法
介绍:通过将64bit中的不同bit划分给一些数据(时间、机器id和自增域),进而保证64bit生成的数据唯一
优点:无网络消耗,性能很高
缺点:时间回拨问题:论文中表述的是采用实际时间,而实际时间有时候会采用历史时间,即使用过去的一些时间,这样就会造成数据重复
- 机器id如何分配问题:机器id需要单独分配,业内目前采用zookeeper和db,但是没有合理的分配和回收方案,存在浪费问题。
机器id占有过少:默认的划分为12个,也就是说一个集群中最多为4096台机器做一个业务,其实也不算少了,但是对共享同一个业务的场景就不再适合
8.美团的Leaf
介绍:采用双Buffer+Db方式获取号段,也支持雪花算法获取
优点:双Buffer+DB:
- 解决号段获取中的性能不是很高问题,可以保持较高的性能
- 雪花算法:
- 无网络消耗,性能很高
- 时间回拨问题解决:时间回拨采用等待方式,算是一种解决方案
- 解决workerId分配问题
缺点:
- 双Buffer+DB:
- 可靠性不高:数据获取依赖于DB,虽然有号段缓存,但是如果在短时间内没有启动,则还是有问题
- 超高并发度支持度:对于一些超高并发度情况下,号段的使用还是会存在网络的数据消耗。不过这个可以通过动态调整号段大小解决,但是动态配置号段过长,则号段浪费也是问题
雪花算法
无网络消耗,性能很高
- 机器id分配解决:通过将机器id的分配方式让用户自定义解决机器id分配问题
- bit动态化:可以让用户根据自己的场景动态的调整对应的bit,进而适配不同的业务场景
缺点:
- 时间回拨问题:时间回拨处理简单粗暴
机器id上限问题:这是个很严重的问题,就是没分配一次就会少一个,虽然上限为22,也就是分配4194304次数就不能再分配了,就会抛出异常
10.滴滴的TinyId
介绍:借鉴美团的Leaf框架中的双Buffer+DB方式并在后端集群方面做了改进
优点:解决号段获取中的性能不是很高问题,可以保持较高的性能
缺点:
- 可靠性不高:数据获取依赖于DB,虽然有号段缓存,但是如果在短时间内没有启动,则还是有问题
- 超高并发度支持度:对于一些超高并发度情况下,号段的使用还是会存在网络的数据消耗。不过这个可以通过动态调整号段大小解决,但是动态配置号段过长,则号段浪费也是问题
