自增 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
  • 雪花算法不是一劳永逸的,时钟回拨必须处理