← 每日面试题 学习看板

分布式ID生成方案都有哪些?

面试题/02架构设计题/02分布式/04分布式ID生成/分布式ID生成方案都有哪些?.md

面试记录 2026-10-10

题目:分布式 ID 生成方案都有哪些?

难度:high(题目 frontmatter 为 high,本面试按 medium 提问)

标签:arch/distributed/id, distributed/id-segment, distributed/id, difficulty/high

评分:⭐⭐⭐⭐☆(4/5)

我的回答

分布式方案是分布式 ID 生成方案。本质其实是两种,一种是中心化的,一种是去中心化的。所谓中心化的就是有一个生成 ID 的服务,然后大家都从这里拿。这时候可以保证获取 ID 的单调递增。但是它存在的问题就是性能上存在问题,并且存在单点问题。另外就是去中心化的。去中心化又有完全去中心化跟不完全去中心化。完全去中心化的是类似于雪花算法、LID 算法这种,它可以在本地去生成,但是它本身去中心化的就有一定的自身的存在的问题需要你处理,比如说它依赖,比如说依赖时间戳保证一致。这时候时间如果不对了,可能会导致 ID 回滚、ID 错误,然后不能单调递增等问题。然后半中心化就是那种一次性从中心的服务去拉取,从生成 ID 的服务中心一次性拉取一批 ID。比如说生成 ID 用一个数据库表,然后这时候一次给一个服务分 1 万个 ID 组,让他先去用,他用完了再申请下一组。每个服务申请一次,申请 1 万或者申请 1000,这时候他有一定的区间去维护自己的服务。这里可能会产生的问题就是区间设置的问题,以及数据 ID 不是完全自增的。但是是区域之争。这是我理解的分布式 ID 生成方案。

点评

优点:

不足:

补充:

完整讲解

第一部分:知识重点剖析

核心考点定位:考察对主流分布式 ID 方案的全面了解,以及按业务场景做选型的能力。

知识点拆解:

  1. UUID:完全本地生成,无状态。UUID v4 随机,v1 基于时间+MAC。优点:无网络调用、无中心依赖;缺点:128 位长、无序、对 B+ 树索引极不友好、无法按业务含义解读
  2. 数据库自增 ID:AUTO_INCREMENT 单机强一致。缺点:数据库成为性能瓶颈和单点,扩展性差。分布式下用步长(START WITH 1, INC 100)分配给不同 DB 实例
  3. 号段模式(Leaf-Segment):从 DB/Redis 一次拉取一个号段(如 1000-1999),本地顺序分配,用完再拉。核心设计是双 Buffer——当前号段快用完时异步预取下一段,避免阻塞
  4. 雪花算法(Snowflake):本地生成,1 符号 + 41 时间戳 + 10 workerId + 12 seq,单机 409.6 万/ms
  5. 百度 UidGenerator:雪花变种,128 位(Long + Long),避免时钟回拨问题,支持单调递增
  6. 滴滴 TinyID:号段变种,支持严格递增和自定义业务前缀
  7. Redis INCR:借助 Redis 单线程原子性实现全局递增 ID,性能极高但有单点
  8. 常见选型矩阵:
递进:需求维度 → 各方案特性 → 关键工程细节 → 选型建议

第二部分:考察方向与延伸递进

考察方向:

延伸递进面试题:

  1. 号段模式的双 Buffer 是怎么工作的?
  1. 雪花和号段怎么选?
  1. UUID 为什么对 B+ 树索引不友好?
  1. Leaf 的两种模式怎么选?

第三部分:面试者参考回答(300-600 字口语化)

面试官您好,分布式 ID 方案的选型我先从维度切:按是否有中心节点分为中心化、半中心化和完全去中心化;按是否有外部依赖分为依赖时钟、依赖中间件、无依赖。业界主流的方案大致有这几类。

完全本地方案:UUID 最简单,UUID v4 是 128 位随机数,无状态本地生成,但缺点是长、无序、对 MySQL B+ 树索引非常不友好,随机插入频繁触发页分裂;ULID 是 UUID 的改进版,26 字符 base32 编码、时间有序。雪花算法是 Twitter 提出的,64 位分段:1 符号 + 41 时间戳 + 10 workerId + 12 序列号,单机可达 409.6 万 ID/ms,主要风险是时钟回拨和 workerId 冲突。百度 UidGenerator 是雪花变种,用 128 位、双 Long 表示,避免了时钟回拨和单调性问题。

依赖中心服务方案:号段模式 是最经典的,代表实现是美团 Leaf-Segment。做法是从 DB 或 Redis 一次拉取一个号段(比如 1000 个),本地顺序分配用完再拉。核心工程技巧是双 Buffer 预取——当前段剩 20% 时异步拉下一段,避免用尽时的服务抖动。号段的 ID 是严格趋势递增(跨段会有跳跃但不倒序),对索引友好,性能仅次于雪花。Redis INCR 也是这一类,借助 Redis 单线程原子性,性能极高但有单点。

数据库方案:MySQL AUTO_INCREMENT 单机强一致但扩展性差。分布式下常用步长分配:多台 DB 各用不同步长(如 100),例如 DB1 生成 1, 101, 201...;DB2 生成 2, 102, 202...,用 DB 主从架构保证高可用。

滴滴 TinyID 是号段的变种,支持严格递增和自定义业务前缀,对金融场景友好。

选型建议:互联网业务优先雪花(性能优先),金融账务优先号段(严格递增),日志埋点用 UUID(去中心化),跨语言生态优先 UUID 或雪花(都容易实现)。工程实践中,美团、滴滴这类大厂往往同时用几种:核心业务用号段,日志用 UUID,用户 ID 用雪花。

整体来说,分布式 ID 没有银弹,选型的关键是看业务对唯一性、递增性、性能、可用性这几个维度的权衡。业务越强一致要求,越倾向号段;性能越敏感,越倾向雪花或 UUID。