从一次撞车开始的旅程
系列的起点是老王的一次事故:两台应用同时写库,订单号撞了。十六篇下来,他从「用数据库自增凑合一下」走到了一套完整的发号体系:号段双 buffer 顶日常,雪花扛高并发,基因法打通分库分表,加密单号挡住爬虫,降级阶梯保住大促。收官这篇不写新知识,把十六篇串成一张作战地图——下次再遇到发号问题,先翻这张图,再动手。
症状速查表
| 症状 / 诉求 | 去哪找药 | 一句话药方 |
|---|---|---|
| 订单号撞车 | 第 1 篇 | 单机自增扛不住分布式,先立唯一性底线 |
| 想图省事用 UUID | 第 2 篇 | 当 token 可以,当主键不行,B+ 树会哭 |
| 要简单可靠的起步方案 | 第 3 篇 | 步长号段,DB 发号的第一正解 |
| 号段吞吐不够、DB 抖 | 第 4 篇 | 双 buffer + 异步预加载 |
| 超高并发、不想碰中心 | 第 5 篇 | 雪花算法,64 位里的精密钟表 |
| 雪花 ID 突然重复 | 第 6 篇 | 先查时钟回拨,NTP 是头号嫌疑 |
| 回拨了怎么办 | 第 7 篇 | 按幅度分级:等待、拒绝、备用机器号 |
| 时钟正常却撞号 | 第 8 篇 | workerID 撞了,克隆镜像先背锅 |
| 小场景不想搭服务 | 第 9 篇 | Redis INCR,算清持久化与主从两本账 |
| 不想手搓想用开源 | 第 10 篇 | Leaf、UidGenerator、Tinyid 按决策树选 |
| DBA 拒绝 UUID 主键 | 第 11 篇 | 趋势递增喂饱 B+ 树 |
| ID 被爬虫遍历 | 第 12 篇 | 归属校验 + 加密映射 + 跳号烟幕 |
| 分表后查不到数据 | 第 13 篇 | 基因法,把路由写进 ID |
| 发号服务挂了 | 第 14 篇 | 三道缓冲 + 降级阶梯 + 兜底标记 |
| 各种诡异事故 | 第 15 篇 | 七个坑,条条是纪律 |
三条铁律
十六篇的知识可以忘,三条铁律要刻在脑子里:
铁律一:唯一性是底线,有序是优化,可预测是风险。三个性质的优先级不能乱——为有序牺牲唯一(时钟回拨硬发号)是事故,为有序暴露规模(连号单号裸奔)是漏洞。凡是冲突,唯一性永远赢。
铁律二:位分配和号段规则是十年合约。纪元起点、基因位数、机房维度、序列位纯净——这些「焊死」决策都要按十年后的规模来定,并写进架构决策记录。改它们的那一刻,历史 ID 全部成为遗留问题。
铁律三:发号器的可用性是全公司的下限。它是被最多链路依赖的基础设施,它降级,下单、支付、物流全部跟着降级。所以它的监控、预案、演练标准,要比普通服务高一个等级。
选型路径一分钟回顾
新业务从零起步的选型路径,浓缩成四步:一问要不要严格单调——要,回号段或 DB;二问团队技术栈——多语言,Tinyid HTTP 上桌;三问吞吐与容忍度——要极致吞吐且容忍洞,UidGenerator;四问时钟运维能力——强,Leaf snowflake;弱,Leaf segment。四步都落空,按第 3 到 9 篇的原理自研,但先读完 Leaf 源码再说。
上线检查清单
发号体系上线前的十项检查,照着打勾:
一,ID 出网转字符串(JS 精度安全);二,workerID 分配机制明确且防克隆撞号(含机房维度);三,时钟回拨治理策略选定并接告警;四,号段 step 按峰值 QPS 估算,buffer 水位有监控;五,ID 耗尽倒计时已预估进监控;六,所有 ID 查询接口归属校验全覆盖;七,敏感对象内外双 ID 分离方案落地;八,降级开关、兜底 ID 标记演练通过;九,位分配表与纪元进架构决策记录;十,发号延迟 P99 与 DB 压力告警接入。十项全绿再上生产,缺一项就补一项——发号这件事,最怕「差不多」。
系列之外
Redis 缓存、MySQL 实战、消息队列、Elasticsearch 检索,加上这套分布式 ID,五个系列拼出了后端主干的大半张地图。分布式体系里还有一块硬骨头与发号器血脉相连——分布式事务:下单扣库存跨了两个库,ID 发得再好,账对不上照样资损。TCC、Saga、本地消息表、事务消息,就是下一个系列的候选主题。老王的 503 咖啡馆还会继续开门,我们下个系列见。
小结
收官一句话:唯一性优先、位分配是长期合约、发号器可用性是公司下限——三条铁律扛走,十六篇的细节都在这张地图上,用的时候来查。分布式 ID 实战系列,全十六篇,完结撒花。
评论 (0)