连载中 4/16

号段进阶:双 buffer 与异步预加载

2026-06-07 · 6417 阅读 · 0 评论 · 0 赞

压测暴露的 RT 毛刺

号段模式上线,日常平稳,大促前全链路压测却暴露了毛刺:99 分位 5ms 的发号接口,隔一阵冒出几个 80ms 的尖刺,间隔大致等于段长消耗完的周期。老王顺着毛刺时间点查,答案就在第 3 篇的设计里:号段用尽那一刻,业务请求线程要同步去 DB 领下一段。DB 平稳时这段路只要几毫秒;DB 一抖动(大促时恰恰最爱抖),领号请求全堵在 DB 行锁上,下游一起排队。

问题本质:取号段的动作发生在请求线程的关键路径上。要消毛刺,就得把这段路挪出去——异步预加载,也就是双 buffer。

双 buffer:发号器里的双跑道

设计思路像机场的双跑道:一个在用,一个在备:

当前段 [1 - 1000]      备用段 [1001 - 2000]
       |
       | 用到 900(10% 警戒线)
       v
后台线程异步领取 [2001 - 3000],放入预备位
       |
当前段耗尽 -> 备用段无缝顶上 -> 再异步预取下一段

三个要点:一是触发时机——当前段消耗到警戒线(常见 10% 到 20%)就启动预取,别等用完,给 DB 预留反应时间;二是切换零成本——备用段在内存里原子换位,请求线程永远只从「当前段」取号,感知不到后台动作;三是持续循环——备用顶上成为当前段的同时,后台马上去领下一个备用,双跑道永远保持。

改造后压测:毛刺消失,99 分位稳定在个位数毫秒。取号段的 DB 访问彻底离开了请求关键路径。

动态 step:段长跟着流量走

段长 step 固定值有个尴尬:设小了,低峰期也会频繁回 DB;设大了,服务重启浪费的号段多,容灾窗口计算也失真。工程化的解法是动态 step(美团 Leaf 的思路):按最近一段时间的发号速率自适应——统计过去若干分钟内的号消耗量,取其数倍作为下一次领取的段长。低峰期段自动变小,大促前段自动变大,DB 访问频率始终维持在合理区间。

老王给发号器加了每小时一次的速率统计,step 在 1000 到 50 万之间浮动,大促当天自动拉满,DB 写压力肉眼可见地平。

容灾时间账:DB 挂了能撑多久

双 buffer 还有第 3 篇没讲透的隐藏价值:把 DB 故障的容灾时间变成可计算的账。算给运营看:

参数数值说明
峰值发号速率1 万个每秒大促下单峰值
当前段剩余最多 30 万警戒线 10% 时正好预取
备用段存量30 万双 buffer 常备
可撑时长约 60 秒60 万存量除以 1 万速率

一分钟,够 DB 主从切换跑完,也够值班同学收到告警。想要更长,把 step 上限调大即可——号段模式的容灾是用内存换时间,而代价只是重启时多废几个号。

预取失败的处理也要定好:后台线程重试加指数退避,连续失败触发告警;内存段见底前最后一搏时,请求线程才允许同步领号——这层兜底平时永不触发,触发说明 DB 真出事了。配合第 3 篇说的已发号段持久化,主从切换回跳的窗口也能被拦住。

小结

双 buffer 一句话:当前段加备用段,异步预取离开关键路径,动态 step 跟着流量走,容灾时间用内存换。到这一步,号段模式已经是生产可用的发号器。但老王的野心不止于此——每秒百万级发号、完全去中心化、连 DB 都不依赖,这就是下一篇的主角:雪花算法。

503

10 年全栈工程师 · 503咖啡馆主理人

#分布式ID#双buffer#异步预加载#动态step#Leaf

评论 (0)

相关推荐

连载中 12/20

排查四件套:jstack、jmap、jstat、jcmd 的实战分工

jstack 看线程在干什么,jmap 看堆里装了什么,jstat 看运行时在变什么,jcmd 是统一入口。四把刀各管一段,配合着用没有查不动的现场。

#jstack#jmap#jstat#jcmd#排查工具
2026-09-16 · 5 阅读 · 0 评论 · 0 赞
连载中 11/20

GC 日志:把回收过程翻译成人话

一行 GC 日志里塞着七种信息:谁触发的、收了哪、停了多久、活了哪些。加上 -Xlog 配置,再加上日志分析工具,GC 不再是只能盯监控曲线的黑盒。

#GC日志#Xlog#日志分析#GC监控#Full GC排查
2026-09-16 · 13 阅读 · 0 评论 · 0 赞
连载中 10/20

ZGC:亚毫秒停顿是怎么炼成的

百 G 大堆停顿不到一毫秒,靠的是把搬家全部挪到并发阶段——着色指针让引用自带状态,读屏障让搬运中的对象依然可访问。代价是吞吐与内存,收益是停顿与堆大小解耦。

#ZGC#着色指针#读屏障#亚毫秒停顿#分代ZGC
2026-09-15 · 8 阅读 · 0 评论 · 0 赞