恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

大厂分布式ID方案对比:Leaf、UidGenerator、Tinyid选型

  • 首页
  • 资讯中心
  • /
  • 大厂分布式ID方案对比:Leaf、UidGenerator、Tinyid选型

相关资讯

基于XSimStudio的仿真建模系统开发实战:从模型接口到实时调优 2026/9/18 2:55:53
在线绘制带任意标注的热图:从坐标计算到网页部署的完整方案 2026/9/18 2:55:53
DeepSeek-R1推理模型提示语公式与工程化接入指南 2026/9/18 2:55:53

最新资讯

平差模型选择与最小二乘实现:从数学原理到工程调试
HMSC联合物种分布模型:群落生态学数据分析的贝叶斯框架实践指南
SpringBoot+Vue+MySQL电影院购票系统:从锁座到订单的全栈解密
oh-my-hermes实战:AI智能体部署与DeepSeek接入全指南
LeetCode 92 反转链表 II 详解:头插法、递归与边界处理
长上下文评测烧 Token,TaoToken 给 DeepSeek-V4.1-Flash 发 Key

今日推荐

2026年AI设计工具在PPT制作中的核心应用与评测
Matlab手写逻辑回归:从数学原理到多变量概率预测模型实现
高值医用耗材研报PDF:用Python完成字段抽取、清洗与趋势预测

本周热门

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化
Flutter应用改名全指南:从Android到iOS的配置与工具实践

本月精选

自研推理加速器Redwood:两周内实现PyTorch模型高效部署的实战教程
V4L2摄像头采集实战:从camera_client.rar到出图全流程解析
从“谁发明了钢琴键”到知识问答智能体:RAG与记忆工程实践

大厂分布式ID方案对比:Leaf、UidGenerator、Tinyid选型

发布时间:2026/9/18 2:55:53
大厂分布式ID方案对比:Leaf、UidGenerator、Tinyid选型 1. 为什么大厂都要自研一套分布式 ID 生成系统先说一个我印象很深的场景。几年前我们做订单系统拆分把原来单一库里的订单表按业务线切成好几张表、好几个库切完之后发现一个特别朴素的问题没人愿意接主键怎么办。以前一张表一个AUTO_INCREMENT简单粗暴、绝对递增、绝无重复什么烦心事都没有。一旦分库分表数据库自己那套自增机制就彻底失效了——不同库各自自增ID 一定撞车。这时候就得靠分布式 ID 生成系统来兜底。所谓分布式 ID就是在多节点、多进程、多库环境下还能稳定产出一个全局唯一、最好是趋势递增的编号。这个编号会被写进订单、支付流水、消息、日志、trace 链路几乎渗透到系统的每一根毛细血管里。所以它不是一个能用就行的小工具而是整个分布式架构的地基之一。地基一抖上面全歪。也正是因为这个位置太关键国内几家体量最大的互联网公司都自己造了轮子美团做了Leaf百度做了UidGenerator滴滴做了Tinyid。这三套东西经常被放在一起比较不是因为它们功能像而是因为它们代表了三条不同的技术路线——号段模式、Snowflake 改良、号段加双 buffer。我把它们通读、跑通、也踩过坑之后最深的感受是没有哪套是最好的只有最贴合你当前约束的那一套。QPS 有多大、能不能容忍趋势递增、运维团队能不能扛住额外组件这几个问题问完答案基本就浮出来了。这篇文章想做的事情很纯粹把这三套系统的设计思路、核心原理、关键参数怎么算、实操中容易翻车的点一层层扒开讲清楚。如果你正在为分库分表后的主键发愁或者要选型、要自己撸一套这篇应该能帮你少走弯路。有基础的同学可以直接跳到对比和实操部分刚接触分布式的也能从基本原理看起。1.1 单机自增 ID 的三大硬伤要理解为什么要自研得先搞清楚单机自增到底死在哪。第一是唯一性失效。分库分表之后每个库都维护自己的自增计数器A 库生成 1、2、3B 库也生成 1、2、3一合并就撞。这不是配置能解决的是机制层面的冲突。第二是性能瓶颈。就算你只有一张表把所有请求都压在数据库的自增列上在高并发写入时这个自增列本身会成为热点锁竞争、页分裂把写入吞吐拖得很惨。我见过一个订单表单库写入到每秒几千就明显卡顿瓶颈就在自增主键的维护上。第三是扩展性差。你想横向扩一台机器就意味着要多一个 ID 产生源而自增 ID 天然期望是唯一且连续的多源之后要么改成区间分配要么加协调组件怎么弄都比单机复杂。所以分布式 ID 系统本质上是把生成唯一编号这件事从一个强中心化的数据库拆成一个可水平扩展、可容灾的独立服务。思路一变天地就宽了。1.2 分布式 ID 的基本诉求清单在选型之前先把需求捋清楚不然后面对比参数的时候会抓不住重点。一个合格的分布式 ID 系统通常要同时满足下面几条而且这些诉求之间往往互相打架需要权衡。全局唯一这是底线任何场景下都不能重复。趋势递增最好单调递增或基本递增因为 MySQL 的 InnoDB 聚簇索引对插入顺序很敏感随机 ID 会导致大量页分裂和随机 IO。高可用ID 服务挂了整个系统的写入就停了所以它必须能容灾。高性能低延迟ID 生成本身不能成为写入链路的瓶颈最好能在本地内存里就拿到。携带信息有时希望 ID 里能反解出时间、机器等信息方便排障。安全不可猜测对外暴露的订单号一般不希望被轻易猜到下一个防止遍历攻击。你看趋势递增和安全不可猜测是天然矛盾的高性能和强唯一保障也经常打架。所以每套方案其实都是在这些诉求里做取舍。下面逐个拆。2. 美团 Leaf号段模式与雪花模式的双保险设计Leaf 我觉得是三套里设计最圆的一个因为它同时提供了两种模式Leaf-segment号段模式和Leaf-snowflake雪花模式业务方按需选。为什么搞两套因为这两个模式的适用场景确实不一样我后面会讲清楚分界线在哪。先看号段模式这也是 Leaf 最有代表性、被抄得最多的设计。2.1 Leaf-segment 号段模式怎么工作号段模式的核心思想特别朴素不再每次去数据库取一个 ID而是一次取一批。数据库里维护一个表记录每个业务当前分配到了哪个最大值每次上游来要号就max_id max_id step往前推一段然后把[max_id - step 1, max_id]这一整段扔给业务方缓存在内存里慢慢用。这样数据库的压力瞬间就降下来了。假设 step 设为 1000那你生成 1000 个 ID 才需要访问一次数据库QPS 直接除以 1000。这是号段模式最香的地方。它的表大致是这么设计的CREATE TABLE leaf_alloc ( biz_tag VARCHAR(128) NOT NULL DEFAULT , max_id BIGINT NOT NULL DEFAULT 1 COMMENT 当前已分配到的最大 id, step INT NOT NULL DEFAULT 1000 COMMENT 每次分配的号段长度, description VARCHAR(256) DEFAULT NULL, update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (biz_tag) );取号的 SQL 也简单到不能再简单UPDATE leaf_alloc SET max_id max_id step WHERE biz_tag order; SELECT biz_tag, max_id, step FROM leaf_alloc WHERE biz_tag order;注意这里是先 update 再 select靠数据库行锁保证并发安全。两个请求同时来一个拿到max_id另一个排队等锁拿到的一定是更新后的值不会重叠。那 step 设多大合适这是个典型的权衡题。step 越大数据库访问频率越低但服务重启或崩溃时浪费的号段越多。比如 step 100000一台机器刚拿了一段就挂了这 10 万个 ID 就凭空蒸发了虽然不影响唯一性但会造成 ID 不连续。我在实际项目里一般把 step 设成 1000 到 10000 之间配合双 buffer 使用效果很稳。2.2 双 buffer 预取解决 TP999 尖刺的关键光有号段还不够Leaf 真正让我服气的是它的双 buffer 机制。问题出在哪呢如果只有一个内存号段当它用到尾、需要去数据库拿下一段时这个请求会阻塞长则几十毫秒。虽然概率不高但落在 TP999 上就是一个明显的尖刺。对一个高频写入的订单系统来说这个尖刺很要命。Leaf 的解法是维护两个号段缓冲区当前正在用的和提前备好的下一段。当当前号段消耗到某个阈值默认 10%时就异步去数据库预取下一段填进备用 buffer。等当前号段真正用完了直接切到备用 buffer整个过程业务无感知几乎零等待。用生活化的说法你不是等家里的米吃完才去买而是厨房还有一袋米的时候就顺手把下一袋备好了永远不落空。参数上LeafAlloc里的update_time还会被数据库监听用来做动态调步长流量涨了自动加大 step流量降了就缩小减少浪费。这套自适应设计用起来确实省心。提示双 buffer 生效的前提是单个号段的消耗速度不要太快。如果你 step 设得极小、QPS 又极高号段可能在异步预取完成前就被吃完了双 buffer 就退化成单 buffer。所以 step 的取值要结合业务 QPS 估算不能拍脑袋。2.3 Leaf-snowflake 与时钟回拨的博弈号段模式的 ID 是趋势递增但不携带任何时间信息有些场景需要从 ID 反解出生成时间来排障就得用雪花模式。Leaf-snowflake 和经典 Snowflake 一样位分配是1 位符号位 41 位时间戳 10 位 workerId 12 位序列号单机每秒可产约 409.6 万个 ID。但 Leaf 在这里做了两个关键改造。第一个是workerId 的分配经典 Snowflake 要求运维手工给每台机器配一个不重复的数字机器一多就容易配错、配重。Leaf 用 ZooKeeper 的顺序节点来分配 workerId服务启动时在 ZK 上建一个持久顺序节点节点序号就是 workerId重启时能复用之前的值彻底免去人工。第二个也是最重要的是时钟回拨处理。雪花算法强依赖系统时钟如果服务器时间被 NTP 同步往回拨了就可能生成重复 ID。Leaf 的策略是分级处理如果回拨幅度在 5ms 以内就等待时钟追上如果超过 5ms说明问题严重直接拒绝服务并返回错误同时上报告警宁可短暂不可用也不产重复 ID。这个取舍很硬核——可用性让位于正确性因为重复 ID 引发的问题比短暂不可用严重得多。注意时钟回拨是雪花类方案的命门。生产环境务必配好 NTP并且考虑多台机器的时钟源尽量一致。我见过因为容器所在宿主机时间漂移导致雪花 ID 重复的事故排查起来极其痛苦。3. 百度 UidGenerator把 Snowflake 塞进 RingBuffer如果你觉得 Leaf-snowflake 每次生成 ID 还要算一遍位运算、偶尔还要处理时钟那百度的 UidGenerator 走的是另一个极端——预生成。它同样基于 Snowflake 改良但把生成的 ID 提前塞进一个环形缓冲区业务来取的时候直接拿走一个几乎就是内存数组的读操作快得离谱。代价是启动时要做一次预热以及运行时要维护这个 RingBuffer。下面拆开讲。3.1 默认位分配与参数计算UidGenerator 默认的位分配和经典 Snowflake 有所不同它是这样切的字段位数说明符号位1 位固定为 0时间戳28 位秒级非毫秒级workerId22 位机器标识序列号13 位同一秒内的自增序号注意时间戳从毫秒级改成了秒级这是个很关键的取舍。秒级时间戳意味着同一秒内要扛下所有并发靠 13 位序列号也就是每秒最多2^13 8192个 ID。这个量级对绝大多数业务足够了但如果你的 QPS 超过 8000就得调整位分配。时间位数决定了系统能撑多少年28 位秒级时间戳可表示2^28 268435456秒约等于 3100 天也就是大概 8.5 年。所以 UidGenerator 需要配一个起始时间点epoch从你部署那天开始算。workerId 22 位可以支持约 420 万台机器理论上够用但实际部署不会到这么多。这套参数不是固定死的BitsAllocator允许你自定义位宽但改之前一定要算清楚时间够不够用、序列号够不够用。我就见过有人把时间戳位砍到 24 位结果系统只能用三年多三年后 ID 直接溢出错乱这种坑是致命的。3.2 RingBuffer 并行预生成机制UidGenerator 最精髓的部分是RingBuffer。它不是你要一个我算一个而是后台有一批填充线程提前把一大批 ID 算好放进环形数组里。业务来取的时候就是移动一下游标从数组里读一个速度快到接近纳秒级。具体机制是这样的RingBuffer 按时间戳秒为单位组织每个槽位对应一秒槽位里放着一个Uid对象里面有一个数组存着这一秒内预生成的 ID。游标随着取号不断前进当发现当前槽位快用完时后台的填充线程就会去准备下一秒的槽位。默认 RingBuffer 大小是2^13 8192个槽位也就是说最多可以缓存未来 8192 秒的 ID当然实际上填充线程是动态跟进的。这套设计的好处是彻底消除生成 ID 时的计算和等待把它变成了纯内存读。但代价是两点一是启动预热服务刚起来时 RingBuffer 是空的需要等填充线程灌一段时间才能用二是内存占用每个槽位都预存了一整秒 8192 个 ID虽然是用的时候才算但总体内存比 Leaf 略高。提示UidGenerator 有两种实现DefaultUidGenerator是实时生成CachedUidGenerator才是 RingBuffer 版。想要极致性能就用后者但记得留够 JVM 内存并给预热留时间。3.3 CachedUidGenerator 的取舍用 CachedUidGenerator 之前得想清楚它带来的额外复杂度值不值。它的优势很明显峰值吞吐极高、延迟极低非常适合那种瞬时流量很大的场景比如秒杀、消息推送造号。但它也有代价一个是workerId 分配它默认用数据库表来记录 workerId 和起始时间启动时往数据库写一条记录靠自增主键拿到唯一的 workerId重启时读回。这比 Leaf 用 ZK 简单但引入了数据库依赖。另一个是时钟依赖依然存在。RingBuffer 是按时间戳组织的如果系统时钟回拨缓存的槽位逻辑就会乱。UidGenerator 对时钟回拨的处理是把时间戳往前拨到一个安全值虽然比 Snowflake 温和但仍然不能无视。所以我的经验是如果你的 QPS 在几千到几万、追求极致性能、能接受启动预热和稍高的内存占用UidGenerator 是很棒的选择如果追求简单、可控、能容忍每次取号有一点点延迟Leaf-segment 更稳妥。4. 滴滴 Tinyid号段模式的极简派实现Tinyid 是滴滴开源的思路和 Leaf-segment 一脉相承都是号段模式但它在工程实现上做得更轻、更直白。我第一次读它源码的时候感觉就是把号段模式该有的东西都做了且没做多余的事。它最大的特点是一个服务能同时给多个业务发号而且提供了 HTTP 和 Java Client 两种接入方式对非 Java 技术栈也很友好。4.1 架构组成与数据模型Tinyid 由三部分组成tinyid-server发号服务、tinyid-clientJava 客户端、数据库表记录各个业务的号段状态。数据模型的核心是一张tiny_id_info表CREATE TABLE tiny_id_info ( id BIGINT NOT NULL AUTO_INCREMENT, biz_type VARCHAR(63) NOT NULL COMMENT 业务类型, begin_id BIGINT NOT NULL DEFAULT 0 COMMENT 当前号段的起始 id, max_id BIGINT NOT NULL DEFAULT 0 COMMENT 当前号段的最大 id, step INT NOT NULL DEFAULT 100000 COMMENT 号段步长, delta INT NOT NULL DEFAULT 1 COMMENT 每个 id 的间隔, remainder INT NOT NULL DEFAULT 0 COMMENT 余数用于取模取号, version BIGINT NOT NULL DEFAULT 0 COMMENT 乐观锁版本号, PRIMARY KEY (id), UNIQUE KEY (biz_type) );跟 Leaf 比多了两个有意思的字段delta和remainder。这是 Tinyid 的一个特色设计——它允许你在一个号段内按固定间隔取号还能用取模的方式让多个业务共享号段而不冲突。什么意思呢比如你想让订单 ID 都是偶数、退款 ID 都是奇数就可以用delta 2配不同的remainder来实现。这个特性在需要按业务分流的场景里挺方便。4.2 双号段与递增步长设计Tinyid 也是双号段内存里维护一个当前号段和一个下一个号段。当前号段快用完时异步去数据库加载下一个号段。这个思路跟 Leaf 的双 buffer 一模一样都是为了避免取号时的阻塞。不过 Tinyid 的步长默认给得很大是100000比 Leaf 常见的 1000 大得多。这背后的考量是Tinyid 承载的是滴滴内部大量业务的发号QPS 很高步长大可以进一步降低数据库压力。但步长大的代价就是我前面说的——服务崩了会浪费更多 ID。Tinyid 用乐观锁version字段来控制并发更新避免多个实例同时改同一个业务的号段。这里有个细节值得说一下Tinyid 号段加载用的是乐观锁 重试而不是 Leaf 那种UPDATE行锁的方式。乐观锁在高并发下会频繁失败重试但号段加载本身频率很低因为 step 大所以影响可以忽略。这个取舍挺聪明——高频操作走内存低频操作走乐观锁。4.3 HTTP 与 Java Client 两种接入方式Tinyid 一个很实用设计是它同时暴露HTTP 接口和Java 客户端。Java 客户端接入的话它会把号段拉到本地内存缓存取号就是本地操作几乎零延迟性能最好。这对 Java 微服务来说是首选。而 HTTP 接口则适合其他语言的服务比如 Python、Go、Node直接发个 HTTP 请求拿 ID。性能比本地缓存差一些但胜在跨语言、无侵入。不过 HTTP 方式有个坑要注意如果网络抖动或 tinyid-server 短暂不可用你的取号就会失败或变慢。所以生产环境一般会在业务侧再缓存一小段 ID减少对 tinyid-server 的直接依赖。这个服务端号段 客户端缓存的双层结构是 Tinyid 抗风险的关键。提示选 HTTP 接入的话务必给 tinyid-server 做多实例部署业务侧配好重试和本地缓存。纯远程调用取号一旦网络出问题会直接拖垮写入链路。5. 三套方案的横向对比与选型建议讲了这么多细节可能你还是想知道到底该选哪个。我把三套方案的关键指标拉一张表出来然后再给一个基于场景的选型判断。这张表是我自己整理、也拿实际测试数据校对过的比空谈原理有用。5.1 核心指标对比表对比项美团 Leaf百度 UidGenerator滴滴 Tinyid核心模式号段 雪花双模式Snowflake RingBuffer号段模式ID 是否含时间号段模式不含雪花模式含含秒级不含趋势递增是基本递增是依赖组件MySQL、ZK雪花模式MySQLMySQL性能高内存号段极高预生成高内存号段接入方式Java Client 为主Java ClientHTTP Java Client时钟依赖雪花模式依赖依赖无启动预热无需要无适合场景通用、需时间信息的业务超高峰值、Java 生态多语言、多业务共用从表里能看出Tinyid 是唯一不依赖时钟的这一点在分布式环境里其实是个不小的优势少了一大类故障源。UidGenerator 性能最高但对运行时环境要求也最高。Leaf 最均衡两种模式覆盖了大部分需求生态和文档也相对成熟。5.2 什么场景选谁我把选型逻辑凝练成几句大白话你对照自己的情况就能定如果你的业务是Java 微服务、QPS 中等、还需要从 ID 反解时间选Leaf号段模式保底、雪花模式补位进可攻退可守。如果你有瞬时超高并发比如秒杀造号、又在 Java 生态里、能接受预热和额外内存选UidGenerator性能天花板最高。如果你的系统是多语言混合、或者一个发号服务要给很多业务共用、不想依赖时钟选TinyidHTTP 接口省心。如果你团队运维力量有限、不想维护 ZK那Tinyid 和 Leaf 号段模式优先避开雪花类的 ZK 依赖和时钟坑。再补充一句我自己的实操体会很多团队上来就想用雪花觉得自带时间信息好排查。但真的落地之后你会发现雪花模式带来的 workerId 管理、时钟回拨处理运维成本并不低。除非你确实有从 ID 看时间的强需求否则号段模式往往更省心。6. 落地实操从零搭一套号段模式 ID 服务看完对比如果你想自己撸一套号段模式的 ID 服务这是最主流、最容易落地的选择我把完整实操过程写下来。这套我实际搭过跑在 MySQL 上单机能轻松扛住每天千万级发号。核心就三块建表、取号逻辑、参数估算。6.1 数据库表设计表结构和前面 Leaf 类似但我加了一些生产环境常用的字段CREATE TABLE id_generator ( biz_tag VARCHAR(128) NOT NULL DEFAULT , max_id BIGINT NOT NULL DEFAULT 1, step INT NOT NULL DEFAULT 1000, version BIGINT NOT NULL DEFAULT 0, update_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (biz_tag) ) ENGINEInnoDB;每个业务一行biz_tag是业务标识。version用于乐观锁更新update_time可以用来做监控——如果某个业务长时间不更新说明它流量很小可以考虑缩小 step。6.2 核心取号逻辑取号逻辑分两层数据库层加载号段内存层分配 ID。加载号段的代码大概是这样的Java 示意public Segment loadSegment(String bizTag) { // 乐观锁更新重试直到成功 for (int i 0; i MAX_RETRY; i) { IdRecord old mapper.selectByTag(bizTag); long newMaxId old.getMaxId() old.getStep() * old.getDelta(); int rows mapper.updateMaxId(bizTag, newMaxId, old.getVersion()); if (rows 0) { return new Segment(old.getMaxId(), newMaxId, old.getStep(), old.getDelta()); } // 更新失败说明有并发重试 } throw new RuntimeException(号段加载失败); }内存分配就更简单了用一个AtomicLong维护当前游标public long nextId() { long current cursor.getAndAdd(delta); if (current currentMaxId) { // 触发异步预取下一段 asyncLoadNextSegment(); } return current; }这里getAndAdd是原子的天然线程安全。当游标撞到当前号段末尾时就触发异步加载业务线程几乎不阻塞。6.3 参数计算与容量估算参数到底怎么定给你一套可复用的估算方法。先看step 该多大。假设你的业务峰值 QPS 是 Q双 buffer 预取一次耗时约 T 毫秒数据库往返那么为了保证预取完成前号段不被用完应满足step / (Q * delta) T / 1000 step Q * delta * T / 1000举个实数Q 5000delta 1T 20ms则 step 5000 * 1 * 20 / 1000 100。也就是说 step 至少 100但为了留足余量和减少数据库访问我一般会取它的 10 倍即 1000 左右。这个数既安全又不过度浪费。再看数据库压力。用了号段之后数据库的访问频率变成Q / step也就是每秒几百到几千次对单台 MySQL 来说毫无压力。这也是号段模式的核心价值所在。最后算ID 可用年限。号段模式用的是 BIGINT理论上限是 2^63-1一个天文数字。就算每秒发 100 万个也要几十万年才用光所以号段模式没有雪花那种时间位数不够用的问题这也是它皮实的一大原因。注意号段模式虽然不会耗尽但要注意多个业务共用一张表时给足隔离。不同业务用不同的biz_tag行互不干扰。曾经见过有人所有业务共用一行结果 step 分配互相打架那场面很绝望。7. 踩坑实录与常见问题排查理论和方案讲完了真正决定成败的往往是那些文档里不会写的坑。下面这些都是我和身边同行真实踩过的整理成速查表希望你能绕开。7.1 时钟回拨引发的 ID 重复这是雪花类方案最致命的问题我把它的触发原因和对策列清楚触发原因现象对策NTP 同步导致时钟回拨生成重复 ID分级处理小幅等待、大幅拒服务容器宿主机时间漂移随机重复容器内避免独立走 NTP手动改系统时间大量重复禁止运维手工改线上时间虚拟机挂起后恢复时间倒退恢复后强制校准时间再启动服务我自己的处理经验是对于号段模式完全不用理时钟对于雪花模式一定要在启动时检查当前时间和上次持久化的时间戳发现倒退就拒绝启动并告警。宁可服务起不来也不能带病运行产重复 ID。7.2 号段耗尽与并发取号异常号段模式常见的问题集中在号段切换和并发加载两个环节号段切换时的小卡顿如果异步预取没配好切换瞬间会有一次数据库查询导致延迟尖刺。解决办法就是双 buffer确保切换时备用段已经就绪。并发加载同一条记录冲突多个实例同时发现号段用完同时去加载乐观锁会频繁失败重试。可以加本地锁 服务端随机退避减少无效并发。号段浪费严重实例频繁重启每次都丢掉半个号段。对策是把 step 调小或者在停止前把未用的号段回写不过回写实现复杂一般不折腾靠调小 step 解决。数据库单点号段模式的数据库一旦挂了新号段取不出来。所以数据库本身要做主从 高可用并且服务侧要把当前号段尽量用满给自己留出恢复时间。提示把号段的状态当前 max_id定期打点上报一旦发现某个业务长时间不更新或号段更新异常频繁都是故障前兆可以提前介入。7.3 监控与告警怎么配ID 服务的监控很容易被忽略但它是保命的。我建议至少配这几个指标发号 QPS 与延迟直接反映服务健康度延迟 P99 突然升高往往意味着号段切换出问题。号段剩余量当前号段还剩多少剩得太少就要警惕预取是否正常。号段加载耗时超过日常基线说明数据库有压力。重复 ID 检测抽样检测极少量 ID 是否重复防止时钟类问题悄悄发生。workerId 冲突雪花模式启动时如果发现 workerId 被占用立即告警。老实说ID 服务平时不出声出起事来就是全站写入挂掉。所以监控不是可选项。我自己就在半夜被 ID 服务告警叫醒过好在提前配了剩余量告警及时干预算不上大故障这钱花得值。8. 我个人在选型和落地中的几点体会最后聊聊我这些年在分布式 ID 这件事上攒下来的一些私人经验不一定都对但都是真金白银换来的。第一能用号段就别急着上雪花。号段模式皮实、简单、不依赖时钟、没有位数耗尽问题覆盖了绝大多数业务。雪花模式那些自带时间信息的好处很多排障场景用日志的 traceId 也能替代不必为了它引入 ZK 和时钟处理。第二ID 服务一定要做成独立服务别塞在业务里。我见过把号段逻辑直接写在订单服务里的结果订单服务一重启好几个业务都受影响。独立部署、独立扩缩容、独立监控才是正路。第三客户端缓存是你的朋友。不管用哪套方案业务侧最好缓存一小段 ID这样即使 ID 服务抖动业务也能撑过一小段时间。这是最后一道防线。第四选型别只看性能运维成本要算进去。UidGenerator 性能最高但它依赖数据库、需要预热、时钟敏感Leaf 功能最全但双模式反而增加了理解成本。真正上线之后你要维护的是这套东西的日常运行而不是它的 benchmark 分数。第五给 ID 加上业务含义要谨慎。有人喜欢把业务类型、时间、机器都编进 ID 里看起来方便但一旦规则变了就动不了。ID 就让它纯粹是个 ID业务信息该查库查库该加字段加字段。耦合越少活得越久。再补一个小技巧如果你要在本地开发环境模拟分布式 ID不一定非要搭 MySQL。号段模式可以用内存变量模拟数据库游标雪花模式可以固定 workerId 跑单机测试逻辑完全够用。真正上线时再切换到正式存储代码结构上把存储层抽出来做接口切换成本就很低。这套东西我已经前后在三个项目里用过从最早的纯 Leaf-segment到后来又试了 Tinyid 的 HTTP 模式每一次都让主键这个老大难问题从天天担心变成基本不用想。那种感觉就像把一个总爱响的报警器终于拆掉了踏实。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号