分布式 ID 与雪花算法
自增 ID 在分库分表后不好使了,UUID 不能排序,雪花算法成了主流。但雪花算法的时钟回拨问题怎么解决?
一、分布式 ID 的核心要求
- 1.1 全局唯一——最基本的
- 1.2 趋势递增——有利于 MySQL InnoDB 索引
- 1.3 单调递增——部分场景需要严格有序
- 1.4 高性能——不能成为瓶颈
- 1.5 信息安全——不能暴露业务量
二、方案 1:UUID
- 2.1 UUID 的 5 个版本
- 2.2 优点——无中心、本地生成
- 2.3 缺点——无序、字符串长、索引不友好
三、方案 2:数据库自增 ID
- 3.1 单库自增——单点瓶颈
- 3.2 多库自增——步长区分
- 3.3 号段模式——一次取一批,减少数据库压力
四、方案 3:雪花算法(Snowflake)
- 4.1 ID 的 64 位结构——1 位符号 + 41 位时间戳 + 10 位机器 ID + 12 位序列号
- 4.2 各部分的作用与取值范围
- 4.3 每个毫秒能生成多少个——4096 个
- 4.4 优点——高性能、趋势递增
- 4.5 缺点——强依赖机器时钟
五、时钟回拨问题详解
- 5.1 什么是时钟回拨——NTP 时间同步导致
- 5.2 回拨的后果——ID 重复
- 5.3 方案 A:抛异常拒绝生成——简单粗暴
- 5.4 方案 B:等待时钟追回——最多等几毫秒
- 5.5 方案 C:备用时钟——记录上次生成时间,回拨时使用备用算法
六、美团 Leaf 方案
- 6.1 Leaf-segment——号段模式,双 buffer 优化
- 6.2 Leaf-snowflake——雪花算法的改进
- 6.3 ZooKeeper 持久顺序节点解决 workerID 分配
- 6.4 时钟回拨的检测与处理
七、总结
- 规模小 → 号段模式足够
- 规模大 → 雪花算法 + 美团 Leaf
- 雪花算法不是一劳永逸的,时钟回拨必须处理
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 谜思录!