IIWAB 美团 Leaf 号段模式 - IIWAB

美团 Leaf 号段模式

IIWAB 1月前 ⋅ 48 阅读

美团 Leaf 号段模式(Leaf-Segment)是一种基于数据库批量预分配 ID 区间的分布式 ID 生成方案,核心是内存发号、异步预取、双Buffer 保障,实现高并发、低延迟、全局趋势递增。


一、核心原理

1. 核心思想

  • 每个 Leaf 服务节点启动时,从数据库批量获取一个 ID 号段(如 [1000, 2000)),缓存在本地内存。
  • 业务请求 ID 时,直接从内存中原子递增分配,不直接访问数据库,大幅提升性能。
  • 号段用尽前,异步预取下一个号段,实现无缝切换。

2. 数据库表结构(核心)

CREATE TABLE `leaf_alloc` (
  `biz_tag` varchar(64) NOT NULL COMMENT '业务标识',
  `max_id` bigint(20) NOT NULL DEFAULT '1' COMMENT '当前最大ID',
  `step` int(11) NOT NULL COMMENT '号段步长(每次申请数量)',
  `description` varchar(256) DEFAULT NULL COMMENT '业务描述',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`biz_tag`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  • biz_tag:业务唯一标识(如 order_iduser_id),不同业务独立号段。
  • max_id:当前已分配的最大 ID,通过 UPDATE 原子更新。
  • step:每次申请的 ID 数量(如 2000),决定数据库访问频率。

3. 双 Buffer 机制(关键优化)

Leaf 使用两个号段缓冲区(当前号段、预备号段),解决号段切换时的阻塞问题:

  1. 服务加载当前号段 A,开始发号。
  2. 当 A 消耗到**10%(可配置)**时,异步预取号段 B
  3. A 用尽后,立即切换到 B,同时异步预取下一个号段 C。
  4. 循环往复,实现无感知、无阻塞的号段切换。

4. 动态步长(自适应)

Leaf 会根据号段消耗速度自动调整 step

  • 若号段消耗过快(如 < 15 分钟),增大 step,减少数据库访问。
  • 若消耗过慢,减小 step,避免 ID 浪费。

二、工作流程(极简版)

  1. 初始化:Leaf 服务启动,根据 biz_tag 查询数据库,获取 max_idstep,生成当前号段 [max_id, max_id+step)
  2. 发号:业务调用 get(biz_tag),从内存中原子递增返回 ID。
  3. 预取:当前号段剩余 < 10% 时,异步执行 SQL:
    UPDATE leaf_alloc SET max_id = max_id + step WHERE biz_tag = 'order_id';
    
    并加载新号段到预备 Buffer。
  4. 切换:当前号段用尽,立即切换到预备号段,重复步骤 2。

三、核心特性

  • 全局唯一:通过数据库原子更新 max_id,保证号段不重复。
  • 趋势递增:ID 整体单调递增,适合 MySQL InnoDB 主键索引。
  • 高并发:内存发号,单机 QPS 可达 5W+,TP99 < 1ms。
  • 高可用:双 Buffer 可容忍数据库短时间宕机(号段未用尽前不影响发号)。
  • 业务隔离:按 biz_tag 独立管理,不同业务互不干扰。
  • 低浪费:步长动态调整,减少 ID 闲置浪费。

四、优缺点对比

优点缺点
性能极高,内存操作依赖数据库(单点风险,需主从)
趋势递增,索引友好号段切换瞬间可能有 ID 空洞
容忍数据库短暂不可用需维护数据库与 Leaf 集群
接入简单,支持多业务水平扩展需依赖数据库原子更新

五、适用场景

  • 订单 ID、用户 ID、支付流水号等需要趋势递增、全局唯一的场景。
  • 高并发、低延迟要求的电商、金融、外卖等业务。
  • 对 ID 连续性要求不苛刻,但需高性能、高可用的分布式系统。

六、与 Snowflake 模式的区别

  • Leaf-Segment:依赖数据库,趋势递增、无时钟问题,适合强依赖有序 ID 的场景。
  • Leaf-Snowflake:纯内存、无数据库依赖,ID 带时间戳,但需处理时钟回拨。

全部评论: 0

    我有话说: