服务从两台扩到六台,订单号偶尔撞车,雪花 ID 的机器号能手写配置吗?
雪花 ID 出现重复或明显倒挂,多数不是算法本身写错,而是它依赖的两条前提被破坏:同一台机器的时间单调向前,不同实例的机器号(workerId)互不重复。按 2026 年常见交付经验,NTP 校时、虚机热迁移、手工改时间都可能让时钟往回跳几十毫秒到几秒;而部署从两台扩到六台时,运维直接复制配置文件里的 workerId,撞号往往比时钟回拨更常见。排查顺序建议固定:先确认机器号有没有撞,再确认是不是回拨,最后才谈换发号方案。
雪花 ID 不重复,靠的是哪几个前提
常见实现是 64 位结构:1 位符号位、41 位毫秒时间戳、10 位机器标识、12 位毫秒内序列。唯一性实际被拆给三个变量:时间、身份、计数。任何一个变量失控,重复都会真实发生,而不只是理论风险。
- 时钟单调:同一机器号上,后一次取到的时间不能小于前一次,否则会重新走一遍用过的号段。
- 身份唯一:机器号与机房号在全部实例中不重复,复制粘贴配置是常见来源。
- 序列不溢出:一毫秒内超过 4096 个请求要等到下一毫秒,不能回绕覆盖。
- 位宽不被挤占:业务前缀、分表位不要吃掉机器位,否则可用实例数会被悄悄压缩。
订单号撞车时,先查机器号还是先查时钟
不要从 ID 长度和格式去猜,把 ID 拆回时间戳段和机器位段再比对。冲突记录集中在同一小段时间窗,更偏向时钟问题;冲突零散分布在多台实例上,更偏向机器号重复。
- 导出冲突记录,看 ID 里的时间戳段是否集中在同一时段。
- 应用日志里找出事实例,核对是否出现时间戳后退或同一秒内跳变。
- 核对该实例近期是否迁移、重启、校时或人工改过时间。
- 核对该实例的机器号来自配置中心还是配置文件手写固定值,跨机房部署是否共用同一段机器位。
只加唯一索引能挡住脏数据落库,但接口会直接报错,用户看到的是下单失败;它是兜底,不是根因修复。
时钟回拨分几档处理,停服不是唯一选项
分级的原因是不同幅度的回拨处理代价差很多:一律停服影响可用性,一律忽略则把重复写进主键。按幅度分档,再加一个恢复动作,比较贴合 2026 年的交付习惯。
- 小幅回拨(经验区间几十毫秒内):自旋等待到上次发号时间之后再继续,等待要设上限,不能无限循环。
- 中等回拨(常见区间几十毫秒到几秒):切换到预留的备用机器号,或借用未来时间戳并从序列号侧扣减,同时打点告警。
- 大幅回拨(阈值常见设在 5 到 10 秒):直接拒绝发号并返回明确错误码,由上游重试或降级,不要静默生成。
- 恢复阶段:确认时钟稳定后再切回原机器号,切换与切回都留记录,便于事后对账。
交付现场:机器号靠手写,扩机器那天最容易翻车
比较典型的一次是周期紧、预算有限、没有配置中心,部署从两台扩到六台,运维直接在配置文件里复制粘贴机器号,测试环境实例少没人发现,上线后订单号偶发唯一键冲突。较稳的做法是把机器号改成启动时向注册中心或号段表申请,申请不到就拒绝启动,实例下线时回收。代价是要多一张分配表和一段回收逻辑,联调通常多花半天到一天,属于常见区间;但比起事后按时间范围清洗重复订单、修补关联表要省得多。这类改造通常先加回拨与撞号检测,再改分配方式,犀跃公司在交付阶段补这块时也按这个顺序推进。
几种发号方式对比着看
选主键方案先问三件事:是否需要趋势有序、能否接受外部依赖、时钟环境是否可控。四项对照如下,数字是经验区间,不是承诺指标。
- 数据库自增:本地简单、单库有序;分库要改步长或另设发号器,跨库写入常多一次往返,压力集中在一处。
- UUID v4:本地生成、无外部依赖、不会重复;无序且字符串偏长,作聚簇主键时插入分散,索引维护成本上升。
- 号段模式:数据库批量取号、内存分发,承载能力与批量大小和缓存策略相关,经验区间从每秒数千到数万;代价是号段表本身要保证可用。
- 雪花类 ID:本地生成、趋势有序、占用空间小;对时钟和机器号敏感,需要配套监控与分配机制,运维投入集中在这一块。
适用与不适用的边界
雪花类 ID 适合订单、支付流水、消息标识这类需要趋势有序、又不想每次取号都打数据库的场景;实例数在几十台以内、机器号能统一分配时,落地风险相对可控。
- 适合:时钟受控的单机房或多机房、写入量较大、希望按 ID 近似还原时间顺序。
- 不适合:宿主机时钟频繁大幅跳变且短期无法改造、实例数接近机器位容量、业务要求 ID 精确表达绝对时间。
- 不必上:日订单量几千、单库单表还没到瓶颈的系统,自增主键或号段模式通常够用,先别引入发号复杂度。
常见问题
雪花 ID 重复了,重启服务能不能先顶一下?
重启只让进程重新读一次时间。时钟仍被回拨或机器号仍冲突时,重启后还会重复,应先定位撞号或回拨原因。
机器位只有 10 位,实例数量超过容量上限怎么办?
可把机器位拆成机房位加实例位,或改用号段模式按业务线发号;超出位宽时不要靠复用机器号硬撑。
容器里时间总比宿主机差几秒,是时区没配对吗?
时区只影响展示,不改变时间戳。差几秒通常是宿主机时钟漂移或未同步时间源,先核宿主机侧。
已经产生的重复订单号该怎么处理?
先冻结发号并修复根因,再按时间范围导出冲突记录人工核对;不建议直接改主键,会牵连关联表。
如果系统已经在用雪花类 ID,可以先做三件事:确认机器号是否统一分配、在发号处加回拨检测与告警、把不同回拨幅度的处置方式写进运维手册。日订单量不大、实例数少、时钟环境简单的系统,不必为此改造主键方案。
-
定时任务两台机器都在跑,月底对账单出了两份,分布式锁到底挡得住哪一段?
日期:2026年11月2日 阅读:19
-
客户门户用 iframe 嵌了我们系统,用户登录完又被弹回登录页,先查 Cookie 还是先查会话?
日期:2026年11月1日 阅读:90
-
把连接池上限从 20 调到 50,早高峰超时反而更多了,连接到底被谁占着?
日期:2026年10月31日 阅读:26
-
用户扫码后手机点了确认,PC 登录页还停在转圈,先查轮询间隔还是先查二维码状态?
日期:2026年10月30日 阅读:38
-
运营把「待发货」改成「等待发货」,后台按钮就集体消失了,状态文案到底该由谁来给?
日期:2026年10月28日 阅读:47




