← 每日面试题 学习看板

分表后全局ID如何生成?

面试题/03数据库中间件/04分库分表/分表后全局ID如何生成?.md

面试记录 2026-09-23

题目:分表后全局 ID 如何生成?

难度:medium

标签:db/sharding, general/knowledge, difficulty/medium

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

我的回答

数据分表后,全局 ID 的生成基本上是通过单独的、独立的 ID 生成器去生成,或者是服务下发的时候直接生成,比如雪花算法之类的,去直接生成 ID,然后设置到数据库中。由于使用这种生成性的数据,它还是保,还能保证全局 ID 的自增性,并且在一定区间内保证它数据是稳定的,不像直接使用 UUID 导致数据分散,并且没有实际的业务意义。这些我们通过自定义的方式生成的全局 ID,可以有实际的业务业务意义,并且可以很好的确认数据的位置跟来源。而且它还可以保证自己数据的自征性,可以更好地被业务理解使用。

点评

优点:

不足:

补充:

完整讲解

第一部分:知识重点剖析

核心考点定位:能否系统列出主流全局 ID 方案,并说清原理、代价和适用场景。

知识点拆解:

  1. 雪花算法(Snowflake):Twitter 开源,64 位 ID 组成:
  1. 号段模式(Segment):美团方案
  1. UUID / UUIDv4:JDK 自带,完全随机
  1. 数据库 auto_increment 单点:所有分片共用一个 MySQL 自增
  1. Leaf 服务(美团开源):Leaf-Snowflake(雪花变体,ZK 分配 workerId)+ Leaf-Segment(号段模式,DB 主备切换)
  1. 基因法(Gene Method):ID 内嵌分片位
  1. 选型四维矩阵:
方案有序高性能分布式防猜测
数据库自增✅❌❌❌
UUIDv4❌✅✅✅
UUIDv7✅✅✅部分
雪花✅✅✅❌
号段✅✅✅❌
基因法✅✅✅❌

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

考察方向:

延伸递进面试题:

  1. 雪花算法遇到时钟回拨怎么办?
  1. 号段模式重启会浪费 ID 吗?会不会重复?
  1. 为什么 UUIDv4 会导致 B+ 树写入性能差 3-10 倍?

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

面试官您好,全局 ID 是分库分表的必备组件,我用六种主流方案来说,重点讲雪花的原理和坑。

为什么必须做全局 ID?分片后每个库都有自己的自增主键,order_0001 和 order_0002 的自增 ID 会重复,业务侧无法用 ID 唯一定位一条记录。所以需要一套跨所有分片唯一的 ID 生成方案。

方案一:数据库自增单点。所有分片共用一个 MySQL 自增列。绝对唯一有序,但单点瓶颈(一般 5-10w QPS 就到头了),也是单点故障源。小业务能用,大业务顶不住。

方案二:UUIDv4。JDK 自带,完全随机,分布式天然。但无序是致命伤——B+ 树随机插入导致 page split 频繁、写入性能差 3-10 倍。除非是纯日志型场景(不需要按 ID 排序),否则不推荐。UUIDv7 修好了这个问题,前 48 位是时间戳,兼具自增和随机。

方案三:雪花算法(Snowflake)——最主流。64 位 ID 分四段:1 位符号 + 41 位毫秒时间戳(约 69 年) + 10 位机器 ID(最多 1024 台机器) + 12 位序列号(单机每秒 4096 个 ID)。优点是本地生成无网络开销、天然有序、性能极高。

雪花的三个坑必须知道:

方案四:号段模式。美团另一套方案。数据库里放一张 ID_SEQ 表存当前号段终点,应用本地缓存 1000 个 ID,用完再去取下一段。1000 次应用请求只换 1 次 DB 请求,DB 压力极低。缺点是应用重启会丢掉未用完的号段(不连续,但保证唯一),大业务一般容忍这个 gap。用双 Buffer 预热能进一步减少浪费。

方案五:Leaf 服务(美团开源):把上面两种封装成 RPC 服务,Leaf-Snowflake 负责小流量低延迟,Leaf-Segment 负责高吞吐。生产可用。

方案六:基因法。ID 内嵌分片位——比如 64 位 ID 的低 4 位存 hash(buyer_id) % 16。查订单时截取低 4 位直接路由到对应分片,不需要额外查用户表就能定位数据。电商必备方案,但要求主键能改(自增 ID 不行,得用雪花)。

选型建议:

一句话总结:雪花是通用默认选项,其他方案都是针对特定痛点的加强版。生产环境我们默认用 Leaf-Snowflake,超高吞吐场景(如秒杀发券)用 Leaf-Segment,需要路由主键时叠加基因法。