分布式发号器

该博客探讨了在分布式环境中如何设计一个发号器,确保生成的序列号全局唯一、有序、可扩展,并在某些情况下支持生成无规则序列号。同时,系统允许业务方自定义序列号混淆策略,以满足不同需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、分布式环境下,保证每个序列号(sequence)是全系统唯一的;

2、序列号可排序,满足单调递增的规律;

3、特定场景下,能生成无规则(或者看不出规则)的序列号;

4、生成的序列号尽量短

5、序列号可进行二次混淆,提供可扩展的interface,业务方自定义实现。

 

方案介绍
单机数据库

主键ID用bigint类型,并且设置为自增、无符号

优点:(1)能够保证唯一性; (2)能够保证递增性; (3)步长固定;

缺点:不支持数据库分不分表,性能低

UUID

UUID是在本地生成的,所以相对性能较高、时延低、扩展性高,完全不受分库分表的影响!

缺点:无法保证趋势递增;用32位字符串表示,占用数据库空间较大;建立索引查询效率低;可能会出现UUID重复的情况

ID分组

1个数据库变成4个库,每个数据库设置不同的auto_increment初始值init,以及相同的增长步长step,以保证每个数据库生成的ID是不同的

缺点:丧失了ID生成的“绝对递增性”;数据库的写压力依然很大;可扩展性差;

segment

分段

Redis和Mysql

Redis数据结构(Hash类型)

key: <string>,表示业务主键/名称
value: {
  cur: <long>,表示当前序列号
  max: <long>,表示这个号段最大的可用序列号
}

取号的大部分操作都集中在Redis,为了保证序列号递增的原子性,取号的功能可以用Lua脚本实现。

Mysql数据结构

{
 bizTag: <string>,  表示业务主键/名称
 max: <long>,  表示这个号段最大的可用序列号
 step: <int>, 每次分段的步长
 timestamp: <long>,  更新数据的时间戳(毫秒)
}

问题:数据中的max扩容,I/O消耗比正常发号要稍多,会遇到“尖刺”

解决:双Buffer模型

SnowFlake

Twitter出品 雪花算法

64位的整型

(1)1位:标识部分,在java中由于long的最高位是符号位,正数是0,负数是1,一般生成的ID为正数,所以为0;

(2)41位:时间戳部分,这个是毫秒级的时间,一般实现上不会存储当前的时间戳,而是时间戳的差值(当前时间-固定的开始时间),这样可以使产生的ID从更小值开始;41位的时间戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年;

(3)10位:节点部分,Twitter实现中使用前5位作为数据中心标识,后5位作为机器标识,可以部署1024个节点;

(4)12位:序列号部分,支持同一毫秒内同一个节点可以生成4096个ID;

问题:机器id的怎么指定;机器id的生成规则;时钟回拨

美团leaf发号器

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

Leaf-segment数据库方案

优点:

  • Leaf服务可以很方便的线性扩展,性能完全能够支撑大多数业务场景。

  • ID号码是趋势递增的8byte的64位数字,满足上述数据库存储的主键要求。

  • 容灾性高:Leaf服务内部有号段缓存,即使DB宕机,短时间内Leaf仍能正常对外提供服务。

  • 可以自定义max_id的大小,非常方便业务从原有的ID方式上迁移过来。

缺点:

  • ID号码不够随机,能够泄露发号数量的信息,不太安全。

  • TP999数据波动大,当号段使用完之后还是会hang在更新数据库的I/O上,tg999数据会出现偶尔的尖刺。

  • DB宕机会造成整个系统不可用。

    采用双buffer的方式,Leaf服务内部有两个号段缓存区segment。当前号段已下发10%时,如果下一个号段未更新,则另启一个更新线程去更新下一个号段。(解决尖刺问题)

Leaf-snowflake

弱依赖ZooKeeper:每次会去ZK拿数据以外,也会在本机文件系统上缓存一个workerID文件

解决时钟问题: 在ZK上注册过:与ZK机器上节点做比较 在ZK上没注册过:abs( 系统时间-sum(time)/nodeSize ) < 阈值

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值