贴吧式
分布式 ID 选型:Snowflake / 号段 / 数据库自增,你们到底怎么分的
帖子正文与楼层回复。
楼主 江砚舟-105
分布式IDSnowflakeLeaf号段模式工程选型
背景
做全栈 3 年,几乎每个新项目第一个要定的就是"主键长什么样"。社区里聊消息中间件、聊 K8s 探针的帖子不少,但分布式 ID 选型这个话题反而很少被认真讨论。我最近做订单号、流水号、库存批次号三条链路的统一 ID 方案,重新翻了一遍自己的笔记,发现当年选型时踩的几个坑,到现在还没想透——想借这个帖子跟各位掰扯一下。
几种常见做法(和它们各自的"隐性税")
- Snowflake / 变种:客户端本地生成,零网络开销,趋势递增;隐性税是时钟回拨(NTP 校准、虚拟机迁移、容器漂移都可能触发),以及 workerId 的分配机制(手写配置?ZK/Redis 抢锁?还是按机房固定?)。
- 号段模式(Leaf / 美团):数据库取号段到本地内存,批量取、批量用;隐性税是双 buffer 的切换抖动(跨号段瞬间 P99 会抖一下)+ 号段表本身变成单点(需要主从或分片)。
- 数据库自增:最简单;隐性税是写热点(InnoDB 单行锁)+ 跨库分片后不全局唯一(要加业务前缀或映射表)。
- UUID / ULID:完全去中心化;隐性税是B-tree 索引随机写,InnoDB 页分裂代价不小,且长度、可读性都差。
我的倾向
在"核心链路 + 有趋势递增诉求"的场景,我倾向号段模式:本地生成 + 双 buffer 平滑切换,时钟完全不受影响,运维成本比 Snowflake + workerId 分配器低一档。
在"非核心 + 无严格顺序诉求"的场景(比如日志 trace id、临时 token),我倾向 ULID:单调、可排序、无中心化依赖,比 UUID v4 更适合做 B-tree 索引。
数据库自增基本只在"单库单表 + 无分片计划"时用,否则迟早要迁移。
想听大家
- 你们线上跑的是哪种?时钟回拨有没有真触发过事故?用的什么兜底(拒绝服务 / 等待 / 回退到上次 ID + 标记)?
- 号段模式的双 buffer 切换,你们是怎么平滑的?P99 抖多少?
- 如果让你重新做一次选型,会不会直接上 Snowflake + 一个集中式 workerId 分配器,把"时钟"问题外包给 NTP + 监控?
- 有没有人用过 Crockford Base32 / NanoID 之类的短编码方案,线上跑下来怎么样?
欢迎直接贴你线上的参数(号段步长、buffer 大小、时钟回拨阈值),空对空的讨论意义不大。
赞 0 · 收藏 0 · 楼层 0
楼层
#1
作者
楼层正文
还没有人回复。