分布式id
ID生成策略
可以自定义加入业务团队id | 年份等其它业务维度来制定策略 ,补充直观性
比如 库位编码,商品编码
带来的好处:如果生成的策略和业务相关
A01-001-23 (库位编码,仓库地点,库区,楼层,通道,层级,库位 …… 库位类型等等)
B-100-2018000001(B表示冷冻品,100表示商品二级分类,后面的表示批次)
snowflake(雪花)
snowflake是twitter开源的分布式ID生成算法,其核心思想是:一个long型的ID,使用其中41bit作为毫秒数,10bit作为机器编号,12bit作为毫秒内序列号。这个算法单机每秒内理论上最多可以生成1000*(2^12),也就是400W的ID,完全能满足业务的需求。
缺点:生成的ID不是很直观
其它生成技术
redis , zk , uuid
redis ,zk
- 实现太重了,需要网络和服务器资源
- 调用链路过长,不用应对高并发的场景
- zookeeper有性能瓶颈
- 读还好,写并发上k级别时,集群越大 写瓶颈越明显
- 半数同意才能提交
- redis cluster ,超高并发下也会有延时 , 性能瓶颈
uuid 不适合筛选,不是趋势递增
自定义分布式ID算法
借鉴snowflake的思想,结合各公司的业务逻辑和并发量,可以实现自己的分布式ID生成算法。
举例,假设某公司ID生成器服务的需求如下:
(1)单机高峰并发量小于1W,预计未来5年单机高峰并发量小于10W
(2)有2个机房,预计未来5年机房数量小于4个
(3)每个机房机器数小于100台
(4)目前有5个业务线有ID生成需求,预计未来业务线数量小于10个
(5)…
分析过程如下:
(1)高位取从2016年1月1日到现在的毫秒数(假设系统ID生成器服务在这个时间之后上线),假设系统至少运行10年,那至少需要10年365天24小时3600秒1000毫秒=320*10^9,差不多预留39bit给毫秒数
(2)每秒的单机高峰并发量小于10W,即平均每毫秒的单机高峰并发量小于100,差不多预留7bit给每毫秒内序列号
(3)5年内机房数小于4个,预留2bit给机房标识
(4)每个机房小于100台机器,预留7bit给每个机房内的服务器标识
(5)业务线小于10个,预留4bit给业务线标识
| 39bit | 4bit | 2bit | 7bit | 预留 | 7bit |
|---|---|---|---|---|---|
| 毫秒数 | 业务线 | 机房 | 机器 | … | 毫秒内序列号 |
64位相当于20位的无符号长整形
59位相当于18位的长整形
这样设计的64bit标识,可以保证:
(1)每个业务线、每个机房、每个机器生成的ID都是不同的
(2)同一个机器,每个毫秒内生成的ID都是不同的
(3)同一个机器,同一个毫秒内,以序列号区分保证生成的ID是不同的
(4)将毫秒数放在最高位,保证生成的ID是趋势递增的
缺点:
(1)由于“没有一个全局时钟”,每台服务器分配的ID是绝对递增的,但从全局看,生成的ID只是趋势递增的(有些服务器的时间早,有些服务器的时间晚)
最后一个容易忽略的问题:
生成的ID,例如message-id/ order-id/ tiezi-id,在数据量大时往往需要分库分表,这些ID经常作为取模分库分表的依据,为了分库分表后数据均匀,ID生成往往有“取模随机性”的需求,所以我们通常把每秒内的序列号放在ID的最末位,保证生成的ID是随机的。
又如果,我们在跨毫秒时,序列号总是归0,会使得序列号为0的ID比较多,导致生成的ID取模后不均匀。解决方法是,序列号不是每次都归0,而是归一个0到9的随机数。
分布式ID生成的服务架构
生成策略
预加载机制
- 提前加载
- 并发获取,使用Disruptor框架提升性能
- 可以使用zk,redis加个业务线的生成规则配置成元数据提供给id生成服务
单点生成方式
- 固定机器生成 ,好处是可以做到全局唯一,缺点就是单点
- 业务规则拼接:机器码+时间戳+自增序列
- 如果需要时间戳 或者 与时钟相关的串 来拼接,则要考虑NTP问题
- NTP问题:高并发下时间校准,ID生成服务器(时间走的比标准的快一些)同步标准时间服务器
- 自增序列:AtomicLong
实现
一定要做兜底(补偿)策略
保证能走通核心链路
(预加载机制+单点生成方式)
实际使用上面两种方式相结合
架构角色功能
-
zk cluster 配置服务中心
- 配置ID规则
- 如果服务业务线过多,可提供id规则的路由服务 提高规则的查询效率
-
定时任务
-
独立服务
-
监控服务id使用率,达到配置的阈值60%就启动任务
-
最好不要在系统使用高峰期间启动任务
-
job (生成id载入到服务本地cache【Guava】和MySQL中,可以防止单点问题,并提高性能)
-
-
Guava缓存
-
DB (MySQL or NoSQL)
-
Mutil Producer
- Service ABC id请求收集
-
WorkerPool Consumer
- id返回
- 由WorkerPool Consumer并发的返回给serviceA,B,C
-
Service A ,B,C,D (各业务线服务)
-
Disruptor框架:可以用它来提高业务并发性能

浙公网安备 33010602011771号