全局唯一ID
2025/12/3大约 3 分钟
为什么在分布式系统中需要全局唯一 ID?
回答:
在分库分表、高并发场景下,如果只依赖单机自增 ID,容易产生重复冲突,难以保证数据唯一性和可追踪性。因此需要一种分布式 ID 生成方案,保证在不同机器、不同库表中生成的 ID 全局唯一、有序、性能高。
分布式 ID 生成的常见方案有哪些?
回答:
数据库号段(Segment)模式
- 每次从数据库取一段号段(如 1000 个),缓存在内存中本地生成。
- 优点:实现简单,ID 有序。
- 缺点:依赖数据库,存在单点。
UUID
- 直接生成随机字符串。
- 优点:本地生成,无中心化依赖。
- 缺点:冗长、无序、查询性能差。
Snowflake(雪花算法)
- 基于时间戳 + 数据中心 ID + 机器 ID + 自增序列。
- 优点:高性能、趋势递增、分布式场景常用。
- 缺点:时钟回拨问题、机器 ID 配置复杂。
Redis / Zookeeper 分布式自增
- 利用分布式缓存/协调器生成 ID。
- 优点:一致性强。
- 缺点:性能瓶颈、可用性依赖。
百度 UidGenerator、美团 Leaf 等中间件
- 开源成熟方案,支持号段模式和 Snowflake。
- 优点:工业级稳定、性能高。
❄️ 雪花算法会有哪些问题?如何解决?
回答:
时钟回拨问题
说明:Snowflake 的 ID 前 41 位是时间戳,要求单调递增。
如果系统时间被调整,比如 NTP(Network Time Protocol,网络时间协议) 回拨了几秒,就会导致时间戳倒退。影响:新生成的 ID 可能比之前的小,甚至和历史 ID 冲突,破坏唯一性。
解决方案:
- 检测时间回拨并等待,直到时间追上。
- 在 ID 中增加回拨标记位,避免与正常 ID 冲突。
- 通过 NTP 定时校时,保证时钟准确。
- 持久化上次时间戳,如果发现回拨则拒绝生成或停机。
机器 ID 重复问题
说明:Snowflake 用 10 位机器 ID 来标识分布式环境中的不同节点,确保不同节点生成的 ID 不会冲突。
如果配置不当,两个节点的机器 ID 一样,它们在同一毫秒生成的 ID 会完全一致。影响:导致分布式节点之间生成的 ID 冲突,插入数据库时会报主键冲突错误。
解决方案:
- 利用注册中心(Zookeeper / Etcd / Nacos)动态分配唯一机器 ID。
- 节点启动时从数据库 / Redis 申请唯一 Worker ID,并定期续约。
- 通过 MAC 地址 / IP 自动计算唯一 ID,避免人工配置错误。
ID 不完全有序 / 数据库写入热点
说明:Snowflake ID 是趋势递增的,但同一毫秒内序列号从 0 开始,跨毫秒时低位会「跳变」。
影响:插入数据库时,大量数据会集中写到索引的最后一页,形成写入热点,降低性能。
解决方案:
- 在序列号中加随机因子,打散写入位置。
- 预留几位做混淆位,让 ID 分布更均匀。
- 结合分库分表路由,降低单表写入压力。
扩展性受限
说明:Snowflake 默认分配位数:
- 时间戳 41 位(可用 69 年)
- 机器 ID 10 位(最多 1024 节点)
- 序列号 12 位(同一毫秒最多 4096 个 ID)
影响:当分布式节点超过 1024 台,或者并发量超过每毫秒 4096 个 ID 时,会遇到生成瓶颈。
解决方案:
- 调整位数分配,比如减少时间戳位数,增加机器 ID 位数。
- 多集群部署,每个集群使用不同的前缀区分。
- 结合数据库号段模式,减少单毫秒内的压力。