返回首页
System Design

Leaf 号段模式:用批量分配降低分布式 ID 压力

分布式系统中的唯一 ID 不仅要求不重复,还要考虑性能、可用性、趋势递增和扩容。Leaf 号段模式的核心思想,是用一次数据库操作批量申请一段 ID,之后在服务内存中高速发放。

基本流程

假设数据库保存 max_idstep

初始 max_id = 0,step = 1000
实例 A 获得 [0, 1000)
实例 B 获得 [1000, 2000)

每个实例在本地使用 AtomicLong 递增,不必为每个 ID 访问数据库,数据库压力从“每次请求一次”降低为“每个号段一次”。

为什么需要原子分配

危险的实现是先 UPDATE,再用另一次普通 SELECT 读取 max_id。多实例交错执行时,读取到的可能不是自己刚刚更新后的结果。

安全方案需要让“锁定记录、计算新区间、更新上界、返回区间”位于清晰的事务边界中,可以使用行锁或数据库支持的原子更新方式,并通过真实 MySQL 并发测试验证不同实例不会获得重叠号段。

双缓冲与预取

当前号段快耗尽时,后台提前加载下一个号段;耗尽后交换 current 与 buffer,避免请求线程同步等待数据库。

这里常涉及:

  • AtomicLong:安全发放单个 ID;
  • volatile:让线程及时看见号段状态;
  • ReentrantLock:保护号段切换和预取;
  • 线程池:执行后台加载任务。

号段大小的权衡

step 太小会频繁访问数据库;太大则在服务重启时浪费更多 ID,并可能让各实例负载不均。ID 不连续通常是可以接受的,因为系统真正要求的是唯一性,而不是每个数字都被使用。

号段模式提供的是“数据库短暂不可用时仍能发放剩余 ID”的缓冲能力,不代表彻底摆脱数据库。监控剩余量、预取失败次数和分配延迟,才能让这个方案真正可运维。