面试知识库
进阶

自增ID与分布式ID#

一句话答案#

单库用自增 ID 简单高效,分布式场景用雪花算法(有序高性能)或号段模式(高可用),UUID 无序不利于索引。

核心要点
方案优点缺点
UUID简单无依赖无序/字符串长/不利索引
雪花算法有序/高性能时钟回拨问题
号段模式高可用/可预分配依赖DB
Redis自增简单有序依赖Redis
面试回答(2分钟版)

单库场景下自增 ID 简单高效,天然有序对 B+ 树插入友好,但在分布式场景存在两个问题:不同库的自增 ID 会冲突,而且会暴露业务量。所以分库分表后需要分布式 ID 方案。主流方案有三种:第一是雪花算法,用时间戳+机器ID+序列号组合出全局唯一 ID,有序且性能极高,但要注意时钟回拨可能导致重复,通常通过等待或拒绝服务来规避;第二是号段模式,应用从数据库批量预领一段 ID 回本地分配,高可用且对外部依赖小,美团 Leaf 就是这个思路;第三是 UUID,完全无依赖但无序导致索引页分裂,不适合做主键。我们项目用的是雪花算法的变种,加了机器 ID 自动注册和时钟回拨检测。

追问与易错

追问方向:

  • “雪花算法时钟回拨怎么处理?”→ 常见方案:小幅回拨(几毫秒)等待追上后继续;大幅回拨直接报错拒绝生成 ID;也可引入机器启动时间戳校验或使用 Leaf-Snowflake 的 ZooKeeper 方案检测回拨
  • “UUID 做主键有什么问题?”→ UUID 无序导致 B+ 树随机插入频繁页分裂,写入性能差;字符串类型占 36 字节远大于 bigint 的 8 字节,索引空间膨胀;二级索引叶子存主键值,主键越大二级索引越臃肿
  • “号段模式怎么实现?”→ 数据库维护一张号段表(biz_tag + max_id + step),应用启动时批量获取一段 ID(如 1~1000)缓存在本地;用完后再申请下一段;美团 Leaf 采用双 Buffer 预加载避免切段时的抖动

易错点:

  • ❌ 自增 ID 没有问题——暴露业务量/分库不唯一
  • ❌ 雪花算法不会重复——时钟回拨时可能重复