Java 面试题

Snowflake雪花算法和分布式ID生成

设计一个分布式ID生成器。讲讲snowflake和它的坑。

为什么面试官会问这道题

中级系统设计常考。Snowflake白板画得下、细节又够多,面试官特别爱问。

如何回答

  1. 1

    Snowflake(Twitter原版)布局:1符号位+41时间戳位(毫秒)+10工作节点位+12序列位=64位long。

  2. 2

    41位毫秒够用69年。10位workerID=1024个节点。12位序列=每节点每毫秒4096个。

  3. 3

    核心坑:时钟回拨。NTP倒拨时钟就会生成重复ID。缓解:拒绝生成、等到追上、借用序列位。

  4. 4

    备选方案:UUID v4(128位随机,不有序——B+树插入烂)、号段模式(从DB取[a,b]本地发——美团Leaf-segment)、Leaf-snowflake(Zookeeper派workerID)。

  5. 5

    数据库原生:TiDB AUTO_RANDOM、Postgres pg_ulid。如果已经在用这些DB可以直接白嫖。

参考回答示例

没特殊理由我默认snowflake——64位long各处都塞得下、大致有序、4096每毫秒每节点管够。坑就是时钟回拨,我见过一次NTP bug把时钟倒拨500ms生成了重复。所以我的生成器记录last timestamp,一旦回拨就拒发、报警、等追回来。workerID用Zookeeper顺序znode分配,扩容自动化。超高写入场景我会加号段模式兜底。UUID v4我只用在DB外(请求ID、幂等键),随机ID会把B+树插入局部性毁掉。

实用技巧

  • 随机UUID做主键能让插入吞吐砍一半——这坑是真的。

  • 时钟漂移担心?编一个"回拨次数"位,拨一次翻一次,不动时间戳。

  • 即答侠会让你默写比特位布局——面试现场自信画出来,印象分加满。

常见问题

为什么不直接用自增?

自增是单库的。分库分表要么中心化(瓶颈)要么冲突。分布式生成器把ID从DB解耦。

Leaf号段 vs snowflake?

号段单调递增、容易猜(对公开URL不安全);snowflake大致有序但不连续。内部业务ID用号段,不希望被猜的场景用snowflake。

面试时担心忘词?即答侠实时助你

即答侠 AI 实时监听面试对话,自动识别问题并即时生成回答建议——无感辅助,让你从容应对每一道题。

免费试用即答侠