分布式id生成算法

分布式id生成算法

背景

在分布式中有很多id要保证是全局唯一的,比如订单id什么的,首先业务上需要唯一,其次遇到分库分表这种,不同的库表中如果只用该表自增的,那么表之间的自增id会重复,因此需要一个方案来生成全局唯一性id

分布式id的要求如下:

1、需要全局唯一

2、需要高性能

3、需要高可用

4、需要好接入

5、递增

常见的算法如下:

数据库自增

专门用一个独立的表主键id自增,作为唯一id,这样是完全可以保证唯一的,但是id长度不一致,在一些场景中,还是需要保证id的长度位数,另外,需要等插入数据库,这个id才知道是什么

最大的缺点就是数据库本来就是系统的瓶颈,在高并发场景下单点db不太适合抗住高并发

可以设置基于数据库集群模式,每台机器初始值不一样,比如一个是0,一个是1,并且递增gap是2,那么两个肯定不会重复,但是不容易扩展,而且这样也不能百分百满足全局递增

redis递增

redis毕竟只是个缓存,拿来做全局递增,有一点微小风险,另外, 如果模式设置不正确,可能会造成重复。

如果是RDB,那么可能会挂掉了但是没有及时存储最新导致id重复

如果是AOF,那么重启恢复时间过长

号段模式

也是利用数据库,但是不同的是,不是每次自增一个来生成一个分布式id,而是一次生成批量个,并且一个业务只需要一条记录,表结构如下,[max_id, max_id+step)就是当前生成的批量id,业务方就可以拿到自己的内存中自己进行处理

CREATE TABLE id_generator (
  id int(10) NOT NULL,
  max_id bigint(20) NOT NULL COMMENT '当前最大id',
  step int(20) NOT NULL COMMENT '号段的布长',
  biz_type	int(20) NOT NULL COMMENT '业务类型',
  version int(20) NOT NULL COMMENT '版本号',
  PRIMARY KEY (`id`)
) 

snowflake算法

snowflake算法是twitter开源的一个分布式id生成方法,算是目前应用比较广发的分布式id算法

snowflake算法其实也很简单,甚至按照自己的角度也能梳理出来,原理如下:

1、首先,分布式id应该是64位,因为32位太小了

2、64位情况下,显然既然要唯一,那么可以根据多个维度进行填充,首先,时间戳,就可以保证唯一,另外,节点可以再去保证不同节点同时并发的唯一性(节点可以看作一个服务的多个实例)

3、同一个节点,为了同一毫秒下保证并发id唯一,需要加上锁

如下图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3XdmOx7-1668505098342)(D:\Users\13045\Documents\notes\img\1668497493562.png)]

总共64个bit,第一个0表示正数,41个bit表示带有毫秒的时间戳(可以自己去试下,时间戳转成二进制确实是41bit), 10bit是工作机器id,也就是允许的最大实例id,后面12bit表示同一个毫秒内单机并发递增是最大能够是2^12=4095

也就是snowflake同意毫秒下支持生成的全局唯一id个数为 2^12 * 2 ^ 10 = 4194304

时钟回拨问题解决思路

1、如果服务所在机器发生了时钟回拨,那么可能会发生id重复,解决办法是,每次生产,都记住最新的时间,下次生成时再对比时间是否更小了,如果更小,则for循环,一直等待知道时间大于上次时间。 但是这个只能用于时间间隔很小的,如果高并发场景,那么显然不太适合

2、另一种方式是百度的UidGenerator方式,不适用时间戳,使用一个自增数就行

3、加入一个新的位,时钟位,可以设置为4位,相应地,调小一点工作节点位和序列号位。 每次发现时钟回拨,也就是当前时间比上一次生成算法的时间还小,并且间隔还比较大,直接等待不太现实,那么就将时钟位位数加1。 但是这样也有缺点,就是不能保证递增

4、Butterfly 算法 https://www.yuque.com/simonalong/butterfly/tul824,跟第二种其实是一个道理

工作id分配和回收

目前机器id需要每台机器不一样,这样的方式分配需要有方案进行处理,同时也要考虑,如果改机器宕机了,对应的workerId分配后的回收问题
可以采用redis自增方式,再做映射,或者使用zk,db

uid-generator

百度开源的,https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

主要特点是使用了RingBuffer数据结构预先生成了uid(生成的时机为初始化时,已经使用的超过了阈值时)并缓存

Leaf

leaf是美团开源的,可切换成两部分: leaf-segement, leaf-snowflake

leaf-segement
leaf-snowflake

leaf-snowflake跟原生snowflake结构一致,特点在于

使用了zk来生成工作id,并且定时去上报时间系统时间

下次启动时,会获取zk上上报的时间,与当前时间比较,判断是否做了机器时钟回调

leaf默认老的节点重新启动,会在zk中永久生效

https://tech.meituan.com/2017/04/21/mt-leaf.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值