发号器方案业内有很多种,我们这里列举如下

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

  • 单点问题:DB宕机,则发号器不可用

    3.数据库多主模式ID

    介绍:采用多主的数据库的自增id,多主之间进行分片切分采用不同步长
    优点:解决数据库自增的单点问题,并无需额外开发,使用简单
    缺点:

  • 扩容复杂

  • 性能不高:瓶颈仍然是DB

    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,虽然有号段缓存,但是如果在短时间内没有启动,则还是有问题
    • 超高并发度支持度:对于一些超高并发度情况下,号段的使用还是会存在网络的数据消耗。不过这个可以通过动态调整号段大小解决,但是动态配置号段过长,则号段浪费也是问题
  • 雪花算法

    • 时间回拨问题:虽然采用等待方式解决,但是如果时钟回拨两次,则会抛出异常
    • workerId分配问题:目前采用zookeeper的顺序节点,只增不减(待确认),集群中达到1024台机器,则会有问题

      9.百度的UidGenerator

      介绍:改造雪花算法,将雪花算法中的字段可自定义,进而根据bit进而适配不同的使用场景
      优点:
  • 无网络消耗,性能很高

  • 机器id分配解决:通过将机器id的分配方式让用户自定义解决机器id分配问题
  • bit动态化:可以让用户根据自己的场景动态的调整对应的bit,进而适配不同的业务场景

缺点:

  • 时间回拨问题:时间回拨处理简单粗暴
  • 机器id上限问题:这是个很严重的问题,就是没分配一次就会少一个,虽然上限为22,也就是分配4194304次数就不能再分配了,就会抛出异常

    10.滴滴的TinyId

    介绍:借鉴美团的Leaf框架中的双Buffer+DB方式并在后端集群方面做了改进
    优点:

  • 解决号段获取中的性能不是很高问题,可以保持较高的性能

缺点:

  • 可靠性不高:数据获取依赖于DB,虽然有号段缓存,但是如果在短时间内没有启动,则还是有问题
  • 超高并发度支持度:对于一些超高并发度情况下,号段的使用还是会存在网络的数据消耗。不过这个可以通过动态调整号段大小解决,但是动态配置号段过长,则号段浪费也是问题

参考:

https://c.lanmit.com/shujuku/MySQL/55820.html