欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

分布式自增ID生成器

程序员文章站 2022-05-03 18:36:42
...

背景

在数据量大的业务中,但数据库压力增加,也便产生了分库分表,但是分库分表的ID不能依赖当前库的自增ID实现,所以,也变需要分布式自增ID生成了

1. 默认步长模式

步长模式的基本思路是,使用一个名为Sequence数据表的一条记录来存储全局的ID当前值。 每个服务实例要获取ID时,先锁住这行记录,将这个值增加,例如加1000,这样这1000个ID就被这个实例独享,在服务自己的内存中慢慢使用,用完时再去数据库改值即可。

缺点:
当内存中的ID用完后,就需要区访问服务去获取新的ID,这样就会又时间延迟;也就是在刷新分布式ID的时候,延迟曲线会又突刺

2. 备用队列步长模式

默认步长模式算法db重新加载ID的时候,由于需要操作db,可能会损耗2-5ms的时间产生尖刺, 备用队列方式内存维护两个队列busy和idle, 当busy分配ID接近高水位的时候,idle队列从db加载ID列表,当busy分配完的时候,将busy队列和idle队列进行交换继续分配ID

缺点:
当ID的消耗大于备用队列的时候,也会产生延迟突刺

大家可以思考一下怎么优化,比如根据消耗速率增加或减少备用队列的长度

3. 雪花模式

基于twitter snowflake算法。

雪花模式基本思路是,将一个64位的long分割为3部分,使用时间递增的特性,来生成唯一的值。

|------- 42bit --------|--- 10bit ---|--- 12bit ---|
|      timestamp       |   workerId  |  sequence   |

其中timestamp为当前毫秒数减去某个固定值(当前固定值取2018.01.01时的毫秒值),workerId占10位,因此可以容纳最多1024个服务实例同时使用。 sequence占12位,是单毫秒内递增值,也就是1毫秒内可以最多4096个值,意味着可以容纳的单个服务实例的最大QPS为4096000。

雪花模式非常依赖服务器时间,所以它的最大问题/隐患在于时间回拨,如果服务器时间回拨,那么就会生成重复的ID。 比如闰秒时的时间回拨,或者由于某些原因管理员修改了系统时间。 虽然在程序中判断了时间需要递增,但是如果在服务重启过程中发生了时间回拨,则无法避免产生相同的ID。

如果服务非常重要,建议使用步长模式;如果服务对错误容忍度高且希望简单方便,使用雪花模式。

思考:雪花模式是不是也可以解决闰秒,重启的分配重复问题呢;通过加锁,上一秒的时间判断等方式,当然也是会降低性能的

还有兴趣的可以了解一下以下的分布式ID生成,看看和上面说的有什么区别

  1. 滴滴Tinyid (备用步长扩展)
  2. 百度Uidgenerator (雪花扩展)
  3. 美团Lead (备用步长扩展)

请大家多多关注微信公众号哦
分布式自增ID生成器