深入浅出分布式 ID 生成方案:从原理到业界主流实现

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
简介: 本文深入探讨分布式ID的生成原理与主流解决方案,解析百度UidGenerator、滴滴TinyID及美团Leaf的核心设计,涵盖Snowflake算法、号段模式与双Buffer优化,助你掌握高并发下全局唯一ID的实现精髓。

在复杂的分布式系统中,随着业务数据量的爆发式增长,传统的单库单表架构往往难以支撑,分库分表成为了常见的扩展手段。而在分库分表的环境下,如何生成一个全局唯一、高性能且高可用的 ID,成为了架构设计中必须解决的核心问题。

本文将探讨分布式 ID 的由来、核心要求,并详细解析业界主流的开源解决方案:百度的 UidGenerator、滴滴的 TinyID,以及重点剖析美团的 Leaf 系统。


为什么需要分布式 ID?

在单体应用或单库单表中,我们通常使用数据库(如 MySQL)的自增主键(AUTO_INCREMENT)来生成 ID。这种方式简单、可靠,且生成的 ID 有序,对数据库索引友好。

然而,在分库分表的场景下,单纯依赖数据库自增就会遇到问题:

  • ID 重复:不同分片上的数据库各自自增,会导致 ID 冲突。
  • 扩展困难:无法通过简单的扩容来解决 ID 唯一性问题。

此外,在微服务架构中,订单号、优惠券码、Trace ID 等都需要全局唯一标识。

分布式 ID 的核心要求

一个优秀的分布式 ID 生成系统,通常需要满足以下指标:

  1. 全局唯一性:这是最基本的要求,不能出现重复 ID。
  2. 高性能:生成 ID 的延迟要低,QPS 要高,不能成为系统的瓶颈。
  3. 高可用:ID 生成服务必须极其稳定,一旦宕机可能导致整个业务瘫痪(如无法下单)。
  4. 趋势递增:最好是趋势递增的(不一定严格连续),这对数据库索引(如 B+ 树)的写入性能非常重要。
  5. 安全性:如果 ID 严格连续(如 1, 2, 3…),容易被恶意爬取或推测业务量,因此在某些场景下需要 ID 无规则。

常见的基础方案

在介绍大厂方案前,先回顾几种基础方案:

  • UUID
  • 优点:本地生成,性能极高,无网络消耗。
  • 缺点:太长(128位,36字符),无序,作为 DB 主键会导致 B+ 树频繁分裂,写入性能差。
  • 数据库自增(多主模式)
  • 利用 MySQL 的 auto_increment_incrementauto_increment_offset 设置步长。
  • 缺点:扩展性差,强依赖数据库,单点压力大。
  • Snowflake(雪花算法)
  • Twitter 开源,由 1bit 符号位 + 41bit 时间戳 + 10bit 机器 ID + 12bit 序列号组成。
  • 优点:不依赖数据库,高性能,有序。
  • 缺点:强依赖机器时钟,时钟回拨会导致 ID 重复或服务不可用。

业界主流开源方案

各大互联网公司基于上述基础方案,针对自身的业务场景和痛点,研发并开源了成熟的分布式 ID 系统。

1. 百度 UidGenerator

UidGenerator 是百度开源的 Java 语言实现的唯一 ID 生成器,基于 Snowflake 算法改进。

核心特点:

  • RingBuffer 缓存:与原生 Snowflake 不同,UidGenerator 采用了双 RingBuffer 结构来缓存 ID,采用了生产者-消费者模型。
  • 一个 RingBuffer 用于存储生成的 ID。
  • 一个 RingBuffer 用于存储状态(Flag)。
  • 这种方式使得 ID 的获取操作变成了纯内存读取,性能极高(QPS 可达 600万+)。
  • 支持自定义 bit 分配:默认的时间戳位较少(28位),支持约 8.7 年,但可以通过配置调整。
  • 解决时钟回拨:通过借用未来时间来解决时钟回拨问题(因为是预生成的)。

适用场景:对性能要求极高,且并发量巨大的场景。

2. 滴滴 TinyID

TinyID 是滴滴开源的分布式 ID 生成系统,它是基于数据库号段模式(Segment)实现的。

核心特点:

  • 号段模式:不每次去数据库取 ID,而是每次取一个“号段”(例如 1000 个 ID),加载到内存中慢慢发,用完了再去取。
  • 多 DB 支持:支持多 DB 源,提高了可用性。
  • TinyID Client(SDK):提供了 Java 客户端。
  • 双号段缓存:客户端也会在内存中缓存双号段(当前使用的和下一个备用的)。
  • 这意味着即使 TinyID Server 挂了,客户端在一段时间内(号段用完前)还能继续生成 ID,极大地提高了容灾能力。
  • HTTP 方式:也支持 HTTP 请求获取 ID,方便非 Java 语言接入。

适用场景:对数据库依赖较高,但希望架构简单、可用性强的场景。TinyID 只支持号段模式,不支持 Snowflake 模式。


3. 美团 Leaf (详细解析)

Leaf 是美团点评开源的分布式 ID 生成系统,它不仅解决了上述方案的许多问题,还提供了极高的稳定性和灵活性。Leaf 这个名字寓意“世界上没有两片完全相同的树叶”。

Leaf 提供了两种生成模式:Leaf-segment(号段模式)Leaf-snowflake(雪花模式)

原文章地址链接https://tech.meituan.com/2017/04/21/mt-leaf.html

3.1 Leaf-segment 模式(号段模式)

Leaf-segment 模式是对数据库自增方案的优化和升级,核心思想是“批量获取”,将数据库的压力降到最低。

1. 数据库设计

Leaf 使用一张表 leaf_alloc 来维护不同业务的 ID 发号进度:

CREATE TABLE `leaf_alloc` (
  `biz_tag` varchar(128)  NOT NULL DEFAULT '', -- 业务标识,如 order, user
  `max_id` bigint(20) NOT NULL DEFAULT '1',    -- 当前已分配的最大 ID
  `step` int(11) NOT NULL,                     -- 步长,每次取号段的长度
  `description` varchar(256)  DEFAULT NULL,    -- 描述
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`biz_tag`)
) ENGINE=InnoDB;

2. 获取号段流程

每次 Leaf 服务去数据库取号段时,执行如下事务操作:

UPDATE leaf_alloc SET max_id = max_id + step WHERE biz_tag = #{tag}
SELECT max_id, step FROM leaf_alloc WHERE biz_tag = #{tag}

这样 Leaf 服务就拿到了 [max_id - step, max_id] 这个范围的 ID(号段),可以在内存中慢慢分配,直到用完。

3. 双 Buffer 优化(核心创新)

简单的号段模式有一个问题:当号段用完时,需要同步去 DB 取下一个号段,这会导致瞬间的线程阻塞和 TP999 飙升。Leaf 采用了 双 Buffer 机制来解决这个问题:

  • 架构:Leaf 服务内部有两个号段缓冲区(Buffer A 和 Buffer B)。
  • 流程
  1. 当前服务正在消耗 Buffer A 中的 ID。
  2. 当 Buffer A 中的 ID 消耗达到一定阈值(如 10% 或 20%)时,后台线程会异步去数据库获取下一个号段,并填充到 Buffer B 中。
  3. 当 Buffer A 彻底用完时,直接瞬间切换到 Buffer B 继续发号,同时 Buffer A 变成备用,后台线程再次去准备下一个号段填充 Buffer A。
  • 效果:除了服务启动时的第一次获取,后续所有的 DB IO 操作都是异步的,获取 ID 的操作变成了纯内存操作,极大地提高了性能和稳定性。

优点

  • 高性能:TP999 极低,ID 生成完全在内存中。
  • 高可用:即使数据库宕机,只要内存中的号段还没用完,Leaf 依然可以坚持一段时间(取决于 step 大小)。
  • 方便扩容:增加 Leaf 服务节点非常简单,无需分库分表。

缺点

  • ID 不随机:ID 是趋势递增的,竞争对手可能推测出业务量(可以通过混淆 ID 解决)。
  • 依赖 DB:虽然有缓存,但最终还是依赖数据库的稳定性。

3.2 Leaf-snowflake 模式(雪花模式)

对于需要 ID 具有时间属性,或者完全不依赖数据库的场景,Leaf 提供了 Snowflake 模式。

1. ID 结构

结构遵循标准的 Snowflake,但对 ZooKeeper 进行了强绑定:

  • 1bit:符号位,始终为 0。
  • 41bit:时间戳(毫秒级),支持约 69 年。
  • 10bit:WorkID(机器 ID),支持 1024 个节点。
  • 12bit:序列号,同一毫秒内支持 4096 个 ID。

2. ZooKeeper 管理 WorkID

Leaf 使用 ZooKeeper 持久顺序节点来自动分配 WorkID:

  1. 启动注册:Leaf 服务启动时,去 ZK 的 /snowflake/${leaf.name}/service/address 下创建一个持久顺序节点
  2. 获取 ID:ZK 返回生成的顺序 ID,Leaf 将其解析为 WorkID(0-1023)。
  3. 本地缓存:Leaf 会将获取到的 WorkID 缓存到本地文件(leaf.properties)。这样即使 ZK 挂了,服务重启时也能读取本地文件恢复 WorkID,属于弱依赖 ZK

3. 解决时钟回拨(三道防线)

Snowflake 最大的问题是时钟回拨,Leaf 做了周全的防御:

  1. 启动校验:启动时,检查本机时间是否小于 ZK 上该节点最后上报的时间。如果是,说明时钟回拨,服务拒绝启动并报警。
  2. 运行时校验:服务运行中,每隔 3 秒向 ZK 上报当前时间。如果发现本机时间小于上次上报时间,说明回拨,暂停服务。
  3. 备用容错:如果 ZK 挂了,会对比本机时间与本地缓存文件中记录的时间。

优点

  • 高性能:无 DB 依赖,纯内存生成。
  • 时间有序:ID 包含时间信息,便于排序和统计。
  • 弱依赖 ZK:ZK 短暂故障不影响核心发号服务。

缺点

  • 依赖 ZK:需要维护 ZooKeeper 集群。
  • 时钟敏感:虽然有防御机制,但系统时间必须精确。

总结

方案 核心算法 依赖组件 优点 缺点
百度 UidGenerator Snowflake MySQL + RingBuffer 性能极高(内存生产),解决回拨 ID 位数配置较复杂,维护 RingBuffer 稍繁琐
滴滴 TinyID Segment MySQL 客户端缓存容灾强,架构简单 不支持 Snowflake 模式
美团 Leaf Segment + Snowflake MySQL / ZooKeeper 双模式灵活切换,双 Buffer 优化非常稳定 需维护 ZK 或 DB

在实际选型中:

  • 如果希望架构简单,对 ID 连续性要求不高,Leaf-segmentTinyID 是很好的选择。
  • 如果需要 ID 包含时间信息,且并发量巨大,Leaf-snowflakeUidGenerator 更合适。
  • 美团 Leaf 由于提供了两种模式的平滑切换和优秀的双 Buffer 设计,是目前业界使用非常广泛的方案。

offer多多.jpg

目录
相关文章
|
1天前
|
自然语言处理 监控 测试技术
互联网大厂“黑话”完全破译指南
互联网大厂黑话太多听不懂?本文整理了一份“保姆级”职场黑话词典,涵盖PRD、A/B测试、WLB、埋点、灰度发布等高频术语,用大白话+生活化类比,帮你快速听懂同事在聊什么。非技术岗也能轻松理解,建议收藏防踩坑。
57 16
|
1天前
|
机器学习/深度学习 人工智能 安全
构建AI智能体:八十六、大模型的指令微调与人类对齐:从知识渊博到善解人意
本文探讨了大模型从知识储备到实用助手的进化过程。首先分析了原始预训练模型存在的问题:擅长文本补全但缺乏指令理解能力,可能生成有害或无关内容。然后详细介绍了指令微调技术,通过高质量(指令-输出)数据集教会模型理解并执行翻译、总结、情感分析等任务。进一步阐述了人类对齐技术,包括基于人类反馈的强化学习(RLHF)的三个关键步骤,使模型输出不仅符合指令,更符合人类价值观。最后展示了Qwen模型微调实践,包括代码实现和效果对比。整个过程将AI从知识库转变为既强大又安全可靠的智能助手。
59 18
|
1天前
|
人工智能 测试技术 API
一线工程师 2025 总结:LLM 只用了不到 10%,剩下 90% 卡在哪?
2025年,LLM能力爆发,但多数企业仅用到其10%。真正瓶颈不在模型强弱,而在工程落地:延迟不可控、并发崩溃、换模成本高、成本失控成常态。当LLM从“工具”变为“基础设施”,中转层与系统稳定性成为关键。释放剩余90%潜力,需扎实的架构设计与工程治理。
|
24天前
|
传感器 网络协议 算法
《多账号同源识别核心技术拆解:从行为指纹到身份锚定的实操逻辑》
本文聚焦同一用户多账号同源识别的核心技术路径,跳出传统单一标识校验思维,深度拆解行为、设备、网络、数据等多维度识别手段的实操逻辑。从行为基因图谱构建、硬件隐性特征聚合,到网络轨迹指纹链打造、交互惯性图谱搭建,再到跨账号数据锚点联动,系统梳理各层级核心技术的落地思路,重点提炼隐性特征萃取、多维度协同校准等关键方法,规避标识篡改、IP切换、行为伪装等识别痛点。通过构建多维度特征融合校准体系,平衡识别精度与隐私合规,形成“全链路特征协同-置信度分级决策-误判动态修正”的闭环逻辑,为复杂场景下多账号精准识别提供兼具深度与实操性的技术参考,助力搭建抗干扰、高精准的同源账号识别体系。
134 11
|
1月前
|
监控 Kubernetes 调度
干货推荐:容器可观测新视角—SysOM 延时抖动监控助力定位业务抖动原因
为了解决这一挑战,本文将结合实战案例,介绍如何在 Kubernetes 环境中使用 ack-sysom-monitor Exporter 对内核延迟进行可视化分析与定位,帮助你快速识别问题根因,并高效缓解由延迟引发的业务抖动。
|
29天前
|
机器学习/深度学习 算法
费曼学习法:为什么你应该通过写博客来掌握任何知识
你是否学完就忘?诺贝尔奖得主费曼提出:若无法简单解释,便是未真正理解。其学习法四步——学习、教授、反思、简化——结合写博客,能深度巩固知识。写作倒逼思维清晰,暴露理解盲区,构建个人知识库。无需完美,从“初学者视角”出发,边学边写,用输出驱动输入。写博客不仅是记录,更是成为专家的路径。开始吧,让文字见证你的深度学习之旅。
330 163
费曼学习法:为什么你应该通过写博客来掌握任何知识
|
13天前
|
SQL 存储 关系型数据库
从一条慢SQL说起:交易订单表如何做索引优化
本文首先以淘天电商交易订单表线上一条非典型慢 SQL 的深入剖析为切入点,示范如何系统地分析与排查慢 SQL;接着详尽归纳了索引分类、B+Tree 与 B‑Tree 的结构差异、B+Tree 高度估算方法、EXPLAIN 与 Query Profile 等诊断工具的使用,以及索引下推与排序的执行流程等索引优化理论;最后结合日常实践经验,提出了适用于大规模线上集群的索引变更 SOP,并总结了常见的慢 SQL 成因与相应的解决策略。
199 36
从一条慢SQL说起:交易订单表如何做索引优化