整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

雪花算法ID重复了?惨痛教训:请勿轻易造轮子!

最近我们线上系统发生了一起严重事故:订单号/流水号出现了重复,影响了核心业务流程。最终定位到根源:一个自研的二方包雪花算法ID生成器出现了问题。

下面我们来回顾一下雪花算法的标准结构,分析问题出在哪,并总结一些通用的设计建议。

一、标准雪花算法()

标准的 ID由一个64位long型整数构成:

txt

代码解读

+----------------------------------------------------------------------------------------------------+
| 1 Bit | 41 Bits 时间戳 | 5 Bits 数据中心ID | 5 Bits 机器ID | 12 Bits 序列号 |
+----------------------------------------------------------------------------------------------------+

优点:

二、我们的“定制版”雪花算法:问题在哪?

我们使用的二方包雪花算法结构如下(根据排查推测):

txt

代码解读

+----------------------------------------------------------------------------------------------------+

雪花算法ID生成器问题_算法分析注册机制作_定制版雪花算法缺陷分析

| 31 Bits 时间戳Delta | 13 Bits 数据中心ID | 4 Bits 工作ID | 8 Bits 业务ID | 8 Bits 序列号 | +----------------------------------------------------------------------------------------------------+

1. 时间戳仅保留31位,最多支持24.85天!2. 用的是 IP 最后一段3. WorkId 和 未配置,全为0最终结果:时间轮回 + IP冲突 + 序列重复,ID彻底撞车。三、教训总结核心组件不建议自研不盲信二方包合理设置机器ID提前覆盖边界场景四、推荐做法

使用成熟的开源实现,如 Hutool、 等:

java

代码解读

// Hutool 示例
Snowflake snowflake = IdUtil.getSnowflake(1, 1);
long id = snowflake.nextId();
// Baomidou 示例(支持从 IP/MAC 自动推导,也可手动指定)
DefaultIdentifierGenerator generator = new DefaultIdentifierGenerator(1, 1); // workerId=1, dataCenterId=1

算法分析注册机制作_定制版雪花算法缺陷分析_雪花算法ID生成器问题

long id = generator.nextId("user");

对于中大型系统, 一般用来标识不同的机房或者 AZ ( Zone)。

的配置策略可以根据系统规模逐步演进:

随着系统规模扩大,推荐逐步引入更复杂但更稳妥的机制,避免一开始就过度设计。

五、其它建议:不要将业务标志拼入ID中

有时我们为了确保唯一性,会试图将业务信息(如类型前缀、模块编号)拼接进ID。但这种做法会带来一系列问题:

更稳妥的做法是将业务字段单独存储,ID仅用于唯一标识和排序。

六、结语

别为造轮子而造轮子,尤其在基础组件上,不可抱侥幸心理。

如果你也有雪花算法的踩坑经验,欢迎交流分享!