← 返回题目列表

号段模式如何设计?

高频 困难 第 12 / 25 题 更新于 2026/10/05
号段模式Leaf双Buffer数据库
学习 AI 实战项目

简化版

号段模式由数据库按业务 key 原子递增高水位,为实例分配互不重叠的 [start,end],实例在内存中发号;双 buffer 提前申请下一段,降低切段延迟并容忍中心短时故障。 安全关键是分段原子性、高水位永不回退、未用区间不复用,以及耗尽时停止发号而非猜测新区间。

详细版

表中保存 biz_tag、max_id、step、version。申请时执行带行锁或 version CAS 的事务,将 max_id += step,成功实例拥有旧值+1到新值。发号使用 AtomicLong,超出 end 后原子切换 buffer。

当前段剩余 10%~20% 或预计耗尽时间小于申请 P99+重试预算时异步预取。步长按峰值和中心 RTO 计算并可分业务动态调整。数据库需主备/共识;从旧备份恢复后先校准到所有历史已分配上界以上。

完整版教学

一、号段模式解决什么

数据库自增每个 ID 都访问中心,吞吐与可用性受数据库限制。号段把一次协调摊到成千上万个 ID 上,实例本地递增即可。它允许空洞和大致有序,换取高吞吐、较低延迟和较简单的时钟模型。

记忆钩子:数据库只负责切蛋糕且每块不重叠,实例负责在自己那块里逐个分发。

二、表结构与原子申请

CREATE TABLE id_alloc (
  biz_tag VARCHAR(64) PRIMARY KEY,
  max_id BIGINT NOT NULL,
  step INT NOT NULL,
  version BIGINT NOT NULL
);

事务读取旧 max=100000、step=10000,更新为 110000;成功后段是 [100001,110000]。并发实例必须通过行锁或 WHERE version=? CAS 串行,先查后改而无锁会分到相同区间。

三、发号与双 Buffer 状态机

CURRENT(100001..110000)
  --剩余15%--> LOADING_NEXT(110001..120000)
  --current耗尽且next ready--> atomic swap

每个 biz_tag 只允许一个加载任务,避免惊群。next 未准备好而 current 耗尽时,可短暂等待有界时间;仍失败就返回不可用,绝不自行把 end 扩大。

四、步长与可用时间

峰值 QPSstep单段理论时间
10001000010s
500010000020s
20000120000060s

目标至少覆盖中心申请 P99 与短时故障,双 buffer 提供额外余量。低频业务用更小 step,动态调整时设置上下限与冷却期。

五、故障恢复和空洞

实例拿到号段后崩溃,未使用部分默认废弃,因此 ID 有空洞。这是避免所有权不确定时重复的安全选择。若尝试回收,必须证明旧进程永久停止并使用 fencing,复杂度通常不值得。

数据库恢复到旧 max_id 会再次分出历史区间。恢复流程应以分配审计记录的“历史已分配上界”为准,或直接跳到事先保存在独立故障域的安全高水位。业务表最大 ID 通常不足以证明安全,因为实例可能仍持有更高但尚未消费完的号段;只有先 fencing 所有旧分配者并证明没有未决区间时,它才能作为辅助证据。数据库备份点本身不是安全发号点。

六、扩展、监控与分库

高并发 biz_tag 可独立行/库,避免一个热行拖累其他业务;跨地域则预分互斥大区间或增加地域命名空间。迁移分配库时确保只有一个权威写中心,并冻结/校验旧库高水位。

监控发号 QPS/P99、current/next 余量、time-to-exhaust、申请失败/CAS 冲突、段切换耗时、step 和浪费。数据表权限应限制人工回退 max_id。

七、常见误区与追问

  • 误区:号段用数据库,所以每次 ID 都慢。 数据库只在申请一段时访问。
  • 误区:实例崩溃后未用号码应回收。 旧实例所有权不明时复用会重复。
  • 误区:数据库主备恢复后可直接继续。 备份中的 max_id 可能低于已发号段。
  • 误区:双 buffer 只需两个 AtomicLong。 还需预取状态、singleflight、原子切换和失败处理。
  • 追问:号段能保证全局递增吗? 区间递增,但实例并行消费导致生成顺序不严格递增。
  • 追问:如何按业务隔离? biz_tag 独立 max/step/指标,热点可分库或专用分配器。
  • 追问:中心库挂了怎么办? 消费已持有段;耗尽后停止,恢复后从安全高水位继续。

八、加强记忆

号段模式按“中心原子划段—本地递增—提前预取—耗尽停发—高水位不回退”理解。双 buffer 优化尾延迟,动态 step 平衡中心压力与浪费,空洞是安全代价。真正需要重点防的是区间重叠和恢复后高水位倒退。