跳到主要内容
新型互联与远程内存

第4章:分离式内存事务系统精读 —— FORD / Motor / LOTUS / AdaptX

拆解四篇里程碑论文的设计权衡:单版本 vs MVCC、锁集中 vs 分散、静态部署 vs 控制面反馈。建立 DM 事务系统的横向比较框架

FORD Motor LOTUS AdaptX RDMA OCC MVCC Distributed Transaction

DM 事务系统是分离式内存领域最成熟也最深度的子方向——FaRM(2014)定下 RDMA OCC 的基本盘后,FORD/Motor/LOTUS 三篇里程碑论文从 2022 到 2025 把”单版本 vs MVCC”、“锁集中 vs 分散”、“静态部署 vs 自适应”三组核心权衡逐一展开。本章不止概述,而是把每个系统的协议拆到可以自己实现的粒度——record 在内存里怎么布局、commit 几步、CAS 对什么字段、abort 怎么回滚——读完这章,看任何 DM 事务新论文你都能秒判它的位置,也能拿起 CREST 自己跑实验

📑 目录


1. 阅读前置:必备的并发控制与 RDMA 基础

读 FORD/Motor/LOTUS/AdaptX 之前,必须先有这几个基础概念。每个概念后面我会标注”在哪一篇论文里以什么形式出现”——这样你读论文时遇到能秒认出来。

1.1 隔离级别

级别含义典型论文用法
Read Committed(RC)不读未提交的数据工业数据库默认
Snapshot Isolation(SI)事务读到一致快照,写不会被中间值污染Motor / LOTUS / AdaptX 默认
Serializable(SR)等价于某种串行执行FORD / Motor 都支持,benchmark 默认 SR

OCC 在 DM 系统里几乎都跑 SR/SI——RC 太弱,实际工业用 SR 就行。论文 abstract 里看到 “Serializable” 不要怵,就是这个 SR

1.2 OCC vs 2PL

维度2PL(两阶段锁)OCC(乐观并发控制)
事务开始取锁不取锁,只读快照
冲突时等待(阻塞)abort 重试
远端 CPU 参与必须(锁状态机)不必须(用 CAS 实现锁)
适合场景高冲突低-中冲突
DM 系统选择❌(需要远端 CPU)

🌟 关键事实:所有 DM 事务系统都用 OCC 而非 2PL——因为 2PL 的”等待”语义需要远端有线程持有锁、被唤醒,违反 disaggregation 原则。OCC 用 CAS 把”取锁”变成一次原子写,远端无感知。

1.3 OCC 三阶段模型

事务 T:
  1. Read phase:    读所有需要的 record,记下版本号(read set)
                    本地修改写集 (write set), 但不提交
  
  2. Validate:      重新检查 read set 的版本号是否还和当初一致
                    如果有变化 → abort & retry
                    如果没变 → 进入 commit
  
  3. Commit:        原子写 write set + 更新版本号
                    用 CAS 取锁 → 写数据 → 写新版本号 → 解锁

所有 DM 事务论文都基于这个三阶段,差异在:

  • read 怎么做(单版本拉一次 / MVCC 拉版本表)
  • validate 怎么做(再读一次 / 用版本号字段比较)
  • commit 怎么做(CAS 锁 + WRITE / 多副本同步 / 异步)
  • 锁在哪里(MN-side / CN-side)

1.4 必备 RDMA 基础:三个原语

原语在论文中的角色
READ(rkey, addr, len)读 read set:一次读 record(可能整 cache-line)。FORD/Motor 大量使用
CAS(rkey, addr, expected, new)8B 原子比较交换:取锁 / 更新版本号。所有 OCC commit 的核心
WRITE(rkey, addr, data, len)写 write set:落数据 + 解锁。一般 doorbell-batched

关键支持的事:

  • 超过 8B 的原子操作:CAS 只能 8B,所以”锁”必须能压进 8B
  • 远端计算:不能让 MN 跑代码,所有逻辑必须 CN 侧

详见第 2 章。

1.5 必备 RDMA 基础:atomic-IOPS 瓶颈

ConnectX 系列网卡的 atomic op(CAS/FAA)有单卡硬上限:

NIC 代际atomic IOPS 上限(单卡)影响
ConnectX-3/4~1 M ops/s早期论文(FaRM)主要瓶颈
ConnectX-5~1.5 M ops/sLOTUS 提”锁分离”的硬件背景
ConnectX-6/6-Dx5-10 M ops/sFORD/Motor 主要测试平台
ConnectX-7估计 15-20 M ops/s仍然不够”无限”

一旦 commit 阶段触发热点 record 的 CAS 排队 → atomic IOPS 占满 → 整个 MN 停摆。这是所有 DM 事务系统不得不绕的核心难题——论文里凡是讲”atomic-IOPS bottleneck”或”hotspot”的地方,根都在这

1.6 必备 RDMA 基础:cache-line 对齐

RDMA NIC 的 DMA 是以 64B 为粒度(cache-line size,x86)。读一个 8B 字段实际上 NIC 也得拉一整 cache-line。FORD 的”cache-line lock + version + data 头部对齐” 设计就是利用这个:一次 READ 64B 同时拿到锁、版本号、数据头

详见第 2 章 §2.2 + §6。

1.7 必备背景:doorbell batching + selective signaling

  • doorbell batching:多个 op 一次 post,摊销 MMIO 代价
  • selective signaling:只让最后一个 op 产生 CQE,前面 op 隐式确认

FORD/Motor/CREST 的 commit 都用这两个优化——第 2 章 §6 讲过。读论文里”batched commit”四个字时心里要画出”N 个 CAS + N 个 WRITE 一次 doorbell”这张图。

🌟 过完这一节,你就具备读 DM 事务论文的最小知识集。下面进入正题。

2. DM 事务的基本设定:CN / MN 分离与 OCC

DM 事务系统的标准物理模型:

       Compute Node (CN)              Memory Node (MN)
       ┌──────────────────┐           ┌──────────────────┐
       │ TXN logic        │           │ Tables / Indexes │
       │ Scheduler        │  RDMA     │ Locks            │
       │ Worker threads   │ ◄──────►  │ Versions         │
       │ (RDMA verbs)     │  100Gbps  │ (NIC-friendly    │
       └──────────────────┘           │  layout)         │
                                      └──────────────────┘
       多节点(可扩)                   多节点(可扩,共享池)

2.1 角色定义

  • CN(compute node):跑事务逻辑、调度、worker 协程,所有计算在 CN
  • MN(memory node):几乎不做计算,只是 NIC + 内存(可以是普通服务器,也可以是 SmartNIC + DRAM,未来甚至是 CXL pool)
  • 协议:OCC 三阶段——Read → Validate → Commit。CN 通过 RDMA one-sided op 直接读写 MN 上的数据

2.2 与传统分布式数据库对比

维度传统分布式 DB(Spanner/Aurora)DM 事务系统
存储节点全栈数据库(SQL 解析 + 优化器 + 存储)仅”裸内存 + NIC”
通信gRPC / 自定义 RPCRDMA verbs
事务协议2PL / 2PC + PaxosOCC + RDMA CAS
扩展性跨 region同 LAN(RDMA 限制)
延迟ms 级µs 级
适用场景全球 OLTP高吞吐 OLTP / 内存数据库

🍎 直觉比喻:DM 事务就像超市自助结账——你自己扫码(CN 算)、自己装袋(CN 整理),结账机(MN)只负责扣款(CAS)。结账机数量有限,人多了排队,这就是 atomic-IOPS 瓶颈。

2.3 为什么不用 2PL

2PL 需要远端 CPU 维护锁状态机:

  • 锁是有”等待队列”的(blocking)
  • 锁有”持有方信息”(owner thread id)
  • 锁有”释放协议”(unlock + 唤醒等待方)

所有这些都需要 MN 侧有线程在跑——违反 disaggregation 原则。

OCC 把锁简化成”用 CAS 原子写一个版本号字段”:

  • 取锁 = CAS(addr, 0, txn_id)(从 0 改成自己的 id,失败=已被占)
  • 解锁 = WRITE(addr, 0)(改回 0)
  • 远端不需要 CPU 介入

2.4 核心难点:atomic-IOPS 瓶颈

DM 系统的 commit 必须用 RDMA CAS / FAA 提交版本号,而 ConnectX 网卡 atomic op 上限 5-10M ops/s(见 §1.5)。

热点数据 + 高并发 → 排队 → abort/retry 风暴:

       100 个 CN 并发 → 同一 record CAS


                    MN 网卡 atomic 单元
                    (5-10M IOPS 上限)

                ┌───────────┴───────────┐
                │ 排队 → 后到的 CAS 失败 │
                │ → CN 看到 abort       │
                │ → CN retry            │
                │ → 又一波 CAS          │
                │ → 死循环 (retry storm)│
                └───────────────────────┘

🧠 关键洞察:所有后续设计(Motor/LOTUS/AdaptX)都在绕这个瓶颈——MVCC 减少冲突、锁分离迁回 CN、控制面 throttle 进入流量。论文里”atomic-IOPS bottleneck” 出现的地方,都是在指向这条主线

3. FaRM(NSDI’14):奠基者

读 FORD 之前必须先理解 FaRM,FORD 的”标杆性”是相对于 FaRM 的

3.1 FaRM 的设定

  • 微软 Bing 团队,2014 NSDI
  • 第一个把 RDMA + OCC 在大规模数据库 workload 上跑通的系统
  • 提出 NIC-assisted transaction 的概念雏形

3.2 FaRM 的事务协议

FaRM commit (简化, 实际更复杂):

1. Lock phase:   对 write set 的每个 record, 发 CAS(lock_addr, unlocked, locked)
                 任何 CAS 失败 → abort

2. Validate:     再 RDMA READ read set, 检查版本号
                 任何不匹配 → 释放已持锁, abort

3. Commit-backup:Primary 写 backup MN(类似 2PC backup)
                 backup 写完才能 commit primary

4. Commit-primary:写新数据 + 新版本号到 primary

5. Truncate:     异步释放锁 + 通知 backup truncate log

3.3 FaRM 的痛点(FORD 要解决的)

  • 每个 record 多次 atomic op:lock 一次、写元数据一次、unlock 一次 → atomic-IOPS 浪费
  • 元数据散布:lock 字段、version 字段、data 不在同一 cache-line → 多次 RDMA READ
  • commit 阶段 RDMA op 数 = O(|write set|),长事务延迟随写集线性增

🌟 FaRM 的贡献是奠基——它定义了”RDMA + OCC + MN/CN 分离”这个范式。FORD 把这个范式优化到接近网络上限

⭕ FaRM 是闭源的(微软内部使用),所以学术界后续工作主要基于 FaRM 的论文 + 自己重写。FORD 是事实上的”开源 FaRM-like”系统。

4. FORD(FAST’22):单版本 + cache-line 锁

FORD(FAST’22, Zhang et al.)是后续所有 DM 事务系统的工程标杆——第一个把 OCC 在 RDMA 网络上跑到 接近网络带宽上限

4.1 核心设计:cache-line 对齐 record

FORD 单条 record 在 MN 内存里的布局:

地址      ┌────────────────────────────────────────────────┐
0x1000  → │  lock (8B)         │ version (8B) │ data...    │  ← cache-line 1
        │  (CAS target)      │ (read 验证)  │            │
0x1040  → ├────────────────────────────────────────────────┤
        │  data... (continued)                            │  ← cache-line 2
        ...

每个 record 起始 cache-line 包含:

  • lock(8B):CAS 目标。0=未锁,非零=持锁者 txn_id
  • version(8B):提交时递增,validate 阶段读这个
  • data(剩余 48B):数据头部直接 inline

读 record 时:一次 RDMA READ 64B(或更多)同时拿到 lock、version、data。后续步骤无需再 RDMA 拉元数据。

4.2 Doorbell-batched commit 详细步骤

假设事务 T 的 write set = {r1, r2, r3}:

Step 1 — Lock phase (一次 doorbell):
    POST CAS(r1.lock_addr, 0, T_id)  ─┐
    POST CAS(r2.lock_addr, 0, T_id)  ─┼─ 一次 ibv_post_send (链表)
    POST CAS(r3.lock_addr, 0, T_id)  ─┘
    
    POLL CQ — 等三个 CAS 全完成
    检查 wc.compare_value:
        - 全部为 0 → 全锁住 ✅
        - 有非零 → 此 record 已被别人锁,abort

Step 2 — Validate (一次 doorbell):
    POST READ(read_set[i].version_addr) for each i  ─┐
    ...                                                │── 一次 ibv_post_send
    POST READ(read_set[N].version_addr)              ─┘
    
    POLL CQ — 等所有 version 读回
    比较:任意 version != 当初读到的 → abort, 释放已持锁

Step 3 — Write (一次 doorbell):
    POST WRITE(r1.data_addr, new_r1_data)        ─┐
    POST WRITE(r2.data_addr, new_r2_data)        ─┤
    POST WRITE(r3.data_addr, new_r3_data)        ─┤
    POST WRITE(r1.version_addr, new_version)     ─┤
    POST WRITE(r2.version_addr, new_version)     ─┤
    POST WRITE(r3.version_addr, new_version)     ─┤── 一次 ibv_post_send
    POST WRITE(r1.lock_addr, 0)                  ─┤  (解锁也合并)
    POST WRITE(r2.lock_addr, 0)                  ─┤
    POST WRITE(r3.lock_addr, 0)                  ─┘
    
    selective signaling: 只最后一个 SIGNALED

关键 op 数:

  • 单写集 record 的 op 数 = 3-4 次 RDMA op
  • 三阶段总共 3 次 doorbell(摊销 MMIO 一次)
  • 整个 commit 延迟 ≈ 3 × RTT (~10 µs 量级)

4.3 FORD 跟 FaRM 的差异(关键!)

维度FaRMFORD
Record 元数据布局lock/version/data 散布cache-line 对齐 + inline
Commit 阶段 op 数O(write set) × 多次O(write set) × 1 次(整批)
Doorbell 数3 次(三阶段)
复制同步 backup commit类似(略有差异,本章不展开)

🌟 FORD 的关键贡献:用 cache-line 对齐把 atomic-IOPS 从”每个字段一次”压到”每条 record 一次”,解决了 FaRM 在小事务上的瓶颈。

4.4 实测性能

(参考 FORD 论文 + 后续复现工作的数据)

  • TPC-C 6 节点(1 MN + 5 CN),100GbE RDMA:~1.5 M txn/s
  • 接近网卡带宽上限(commit 阶段几乎打满 RDMA 通路)
  • 单事务延迟中位数 ~30-50 µs

4.5 FORD 的局限(后续工作要解的)

  • 单版本 → 长事务读会被写阻塞(读到中间态需要重试)
  • 锁集中在 MN → MN 网卡的 atomic-IOPS 仍是瓶颈(高冲突时 abort 风暴)
  • 静态部署:replication / sharding 一次定好,负载漂移就退化
  • 写放大:每次 commit 至少 N 次 WRITE(数据 + 版本号 + 解锁),热点 record 反复写

5. Motor(OSDI’24):MVCC + 一致版本表

Motor(OSDI’24, Wu et al.)把 FORD 的”单版本”升级到 多版本(MVCC),主要解长事务/混合负载的痛点。

5.1 核心设计:Consecutive Version Table (CVT)

普通 MVCC 的版本链是链表:

record A:
  v1 (head) → v2 → v3 → v4 → ... 
              ts=100, ts=200, ...

链表对 RDMA 不友好——遍历要多次 RDMA READ(指针追逐)。

Motor 的 CVT 是紧凑、定长、cache-line 友好的:

record A 在 MN 内存里(简化布局):

地址      ┌──────────────────────────────────────────────────┐
0x2000  → │ lock  │ slot_idx │ slot[0] │ slot[1] │ slot[2] │ slot[3] │
        │ (8B) │  (8B)    │  v1     │  v2     │  v3     │  v4     │
        │      │          │ ts=100  │ ts=200  │ ts=300  │ ts=400  │
        └──────────────────────────────────────────────────┘
                            ↑ slot_idx 指向最新版本 (循环利用)
  • 每条 record 有固定 K 个版本槽(K = 4-8,论文实验用 4)
  • 写操作 round-robin 覆盖最旧的槽,slot_idx 指向当前最新位置
  • snapshot read 一次 RDMA READ 拿整个 CVT(几个 cache-line),CN 端按时间戳挑合适版本

5.2 Snapshot Read 详细流程

1. CN 想读 record A 在 ts=250 时的版本
2. RDMA READ A 整块 (一次 op, ~256B):
   → 拿到 slot_idx + 全部 slot 数据
3. CN 在本地按时间戳挑:
   slot[0]: ts=100 (太旧)
   slot[1]: ts=200 ← 选这个 (最大但 <=250)
   slot[2]: ts=300 (太新)
4. 返回 slot[1] 的数据

无需遍历版本链,无需多次 RDMA op。

5.3 写操作流程

1. CN 取锁: CAS(record.lock_addr, 0, txn_id) — 同 FORD
2. CN 读当前 slot_idx: 走 RDMA READ
3. CN 计算下一个 slot 位置: next_idx = (slot_idx + 1) % K
4. CN 写新 version 到 slot[next_idx]: WRITE(slot_addr, new_data + new_ts)
5. CN 更新 slot_idx 到 next_idx: WRITE(slot_idx_addr, next_idx)
6. CN 解锁: WRITE(record.lock_addr, 0)

写放大:相比 FORD 的”覆盖原版本”,Motor 多写一个 slot_idx。但老版本不丢——这是 MVCC 的本质收益。

5.4 Garbage Collection

CVT 大小 K 是定长——最旧版本会被覆盖。安全前提:没有任何活跃事务还在引用这个版本

Motor 用 全局时间戳水位线 (GTSW):

  • 每个事务开始时拿一个 ts(全局递增)
  • 系统跟踪所有活跃事务的最小 ts (= GTSW)
  • 任何 ts < GTSW 的版本可以被安全覆盖

GTSW 推进协议:CN 周期性把”我目前活跃的最小 ts”上报给一个 coordinator(可以用 RDMA atomic FAA 实现),coordinator 算出全局最小并广播。

5.5 Motor vs FORD 对比

维度FORDMotor
版本模型单版本MVCC(K 个槽)
长事务读容易 abort(读到写中间态)友好(读老版本不冲突)
写放大~1.5-2×(写 + 整理 CVT)
单条 record 内存占用~64B~256B (K=4)
适合场景短 OLTP(TPC-C)混合 OLTP/OLAP

🌟 Motor 的关键贡献:证明 MVCC 在 RDMA disaggregation 设定下也能做到”读多写少”工作负载下 ~2× FORD,代价是写放大与内存占用。

5.6 Motor 的局限

  • 写放大仍然吃 RDMA 带宽
  • CVT 大小 K 是静态参数,选小了重要版本被覆盖、选大了浪费空间
  • 锁仍然集中在 MN → atomic-IOPS 瓶颈未解决

6. LOTUS(2025):锁也分离 + 反应式再均衡

LOTUS(论文 2025 年发表)是 第一个明确把”锁的位置”作为一阶设计变量 的工作。

6.1 核心洞察

atomic-IOPS 瓶颈在哪里?在 MN 网卡。那如果把锁迁回 CN 呢?

6.2 LOTUS 的锁布局

FORD/Motor:                       LOTUS:
  ┌────────┐                       ┌────────────────┐
  │  MN    │                       │   CN-side      │
  │  ┌──┐  │                       │   hash table   │
  │  │锁│  │ ← CAS 集中在 MN       │   (per-CN 一份)│
  │  └──┘  │                       └────────────────┘
  └────────┘                              │
                                          │ 跨 CN 协调
                                  ┌───────┴───────┐
                                  │ Lock service  │
                                  │ (协议)        │
                                  └───────────────┘

每个 CN 有一份 本地 lock hash table,key = (table_id, record_id)。取锁时:

  1. CN 在本地 hash 表里查询,如果记录已被本 CN 持有 → 直接重入(或冲突)
  2. 跨 CN 时,用一个分布式锁服务协议(论文里有详细协议,大致是基于 RDMA write + 自定义协议,绕开 CAS)

6.3 跨 CN 协调协议

LOTUS 论文里给的协议大致框架:

  • 每个锁有一个 leader CN(根据 record_id 哈希到固定 CN)
  • 申请锁时,CN A 通过 RDMA WRITE(不是 CAS!)向 leader CN 的 lock 表写”我要锁”
  • Leader CN 异步处理(用一个 polling 线程检查这个表)
  • Leader CN 同意后回 ACK(也是 RDMA WRITE)

🍎 直觉:把”锁原子操作”从硬件 CAS 转换为”软件协议”,牺牲单次 op 速度换吞吐——RDMA WRITE 的 IOPS 远高于 CAS。

6.4 Reactive Rebalancing(~100ms)

LOTUS 的另一创新:运行时监控负载,触发 shard 迁移

监控
  └─ 每 N ms 收集 CN-side 的负载/冲突率
  
负载不均判定
  └─ 如果某 CN 的 lock contention 率显著高于平均
  
触发迁移
  └─ 把热 shard 从一个 CN 迁到另一个 CN
  └─ 数据复制(RDMA WRITE)
  └─ 锁状态转移
  
反应窗口: ~100 ms

6.5 LOTUS 的局限

🌟 LOTUS 的关键贡献:第一次用控制面思想做 DM 事务——不再”一次部署到底”,而是运行时反馈调整 shard 位置。本质是控制面的雏形。

但仍然不够:

  • 100ms 反应窗口对短突发热点仍然太慢(想象 200ms 的热点突发,LOTUS 100ms 之后才开始迁,迁完热点已经过了)
  • 锁迁回 CN 之后,跨 CN 协调本身有开销(需要跨 CN 一致性协议)
  • 仍然是单一控制环路(只看 shard 迁移),没有解决 retry storm 类问题
  • shard 迁移本身代价大:数据搬运 + 锁状态转移,迁移期间该 shard 暂停服务

7. AdaptX(2026,本系列):控制面抽象 + 5ms 反馈环 ⭐

AdaptX 是本系列(本指南作者)的工作,把 LOTUS 的”反应式调整”思路进一步抽象成控制面框架,并把反应窗口从 100ms 压到 5ms

⭐ 注:这一节是本系列作者工作,正在 ATC 投稿迭代中,数据为内部实测。

7.1 控制面 4-tuple 抽象

每个控制环路定义为 ⟨Signal(信号), Actuator(执行器), Rule(规则), Composition contract(组合契约)⟩

元素含义例子(Loop A)
Signal测什么abort rate(取自 OCC validation 阶段)
Actuator控什么admission rate(限流/放行决策)
Rule怎么从 signal 推 actuatorAIMD(增加放行 / 倍减)
Composition与其他环路如何共存signal-disjoint + actuator-disjoint

7.2 Loop A:Retry Storm Throttle

问题:OCC 的 abort 触发 retry,retry 又会触发新一轮 abort——典型 retry storm,导致 thpt 崩盘。

Loop A 设计:

  • Signal:CN 端观察的 abort rate(滑动窗口,5ms 间隔统计)
  • Actuator:每个 worker 的入队速率 admission control(决定 worker 是否能拿新事务)
  • Rule:AIMD(TCP NewReno 风格)
  • 反应窗口:5ms(阈值跨过 → 立即调整)

AIMD 数学

参数:

  • h:abort rate 阈值,默认 0.35
  • α:倍减因子,默认 0.5(超阈值时 admission 减半)
  • δ:加性增,默认 4(每次 tick 增加 4 个 admission slot)
  • NF:noise floor,默认 2(admission 不能低于这个值)

每 5ms tick:

abort_rate = abort_count / total_count   # 上一窗口
if abort_rate > h:
    admission = max(NF, admission * α)   # 倍减
else:
    admission = admission + δ            # 加性增

直觉:超热时倍减(快速降流量)、平稳时小步增(慢慢摸索上限)——和 TCP 拥塞控制完全同源。

实测数据

extreme regime(1/40 仓库 95% 概率热点)下:

  • baseline:thpt = 0.05 Mops/s, P99 = 30ms
  • Loop A:thpt = 0.095 Mops/s (1.91× baseline), P99 = 100ms (3.4×)
  • Bootstrap 95% CI: [1.02×, 2.48×]

throughput 显著提升,P99 略变差(throttle 增加了排队等待,但避免了 retry storm)。

7.3 Loop B:NIC IOPS-aware Replica Read

问题:Motor MVCC 的 backup 副本本来只用作 fault tolerance,read 都打 primary。但 primary MN 的 NIC 满载时,backup MN 是闲置的——能不能动态分流?

Loop B 设计:

  • Signal:每个 MN 的 NIC IOPS(从 mlx5 hw_counters 读 rx_read_requests / rx_write_requests / rx_atomic_requests)
  • Actuator:CN 选择副本(primary 还是 backup)
  • Rule:把读流量倾向到 IOPS 更低的副本
  • 与 Loop A 组合:signal disjoint(abort rate vs IOPS)、actuator disjoint(限流 vs 副本选择)

信号采集

// MN 侧 publisher:每 5ms 读 hw_counters, 写到 MR 暴露的一个 8B slot
uint64_t rx_reads = read_sysfs("/sys/class/infiniband/mlx5_2/ports/1/hw_counters/rx_read_requests");
uint64_t rx_writes = read_sysfs(".../rx_write_requests");
uint64_t rx_atomics = read_sysfs(".../rx_atomic_requests");
uint64_t total = rx_reads + rx_writes + rx_atomics;

// 写 IOPS 速率 = (current - last) / interval
uint64_t iops = (total - last_total) * 1000 / 5;  // ms → s
*mr_slot = iops;  // CN 通过 RDMA READ 拉这个值

CN 侧选择

int SelectReplica(int primary_mn, vector<int> backup_mns) {
    int best = primary_mn;
    uint64_t best_iops = nic_iops[primary_mn];
    for (int m : backup_mns) {
        if (nic_iops[m] < best_iops * 0.7) {  // 阈值: 比 primary 低 30%+
            best = m;
            best_iops = nic_iops[m];
        }
    }
    return best;
}

Loop B 一致性策略

backup 上的版本可能略旧——读到老版本怎么办?两条策略:

  • OCC version-check fallback:读 backup 拿到 (data, version),如果 OCC validate 阶段 version 不匹配 primary → fallback 重读 primary
  • Stale read 容忍:对 read-only 短查询,允许稍微 stale 的快照(类似 Spanner stale read)

7.4 与 LOTUS 的对比

维度LOTUSAdaptX
反应窗口~100 ms~5 ms (20× 快)
控制环路数1(shard rebalance)2+(Loop A + Loop B + 可扩展)
抽象ad-hoc heuristic4-tuple + composition contract
失败模式分析简略alt-extreme regime 反例完整披露
开源部分✅ CREST patch

7.5 AdaptX 的局限和坦白

  • alt-extreme(2/40 仓库 92% 概率热点) regime 上 Loop A 反而 0.87× baseline——signal trigger 不准导致误调,这是控制面的固有 false-positive 风险
  • 5ms 窗口需要 RDMA 同步的特殊编码,不是所有平台都易实现
  • Loop B 端到端依赖双 MN 拓扑,需要 backup 副本(写放大 2×)
  • 当前两个环路都是经验阈值(h=0.35 等),没有形式化收敛证明

AdaptX 的真正价值是”把 LOTUS 单环路扩展成框架”——这意味着第三、第四个控制环路(比如基于 PCIe utilization 的 NIC 选择,基于队列深度的 batch 大小)可以按同一抽象增量加入,而不是重写整个系统。

🌟 关键贡献:把”自适应”从 ad-hoc 启发式提升为可组合的控制面框架,并证明 5ms 反应窗口是可达的(LOTUS 100ms → AdaptX 5ms,两个数量级)。

8. 横向对比矩阵:四个系统站在 design space 哪里

                          数据面演化
                         ────────────────►
                单版本           MVCC          多副本 + reactive
              ┌──────────┬──────────┬─────────────────┐
              │   FaRM   │   FORD   │     LOTUS       │
              │ (2014)   │ (FAST'22)│  (2025)         │
              │   锁在MN │   锁在MN │   锁在CN        │
              ├──────────┼──────────┼─────────────────┤
              │          │  Motor   │                 │
              │          │ (OSDI'24)│                 │
              │          │  MVCC+CVT│                 │
              │          │   锁在MN │                 │
              ├──────────┴──────────┴─────────────────┤
              │             AdaptX (2026)              │
              │     控制面框架 + 多环路 + 5ms 反馈     │
              └────────────────────────────────────────┘

                                              控制面演化
系统版本模型锁位置反馈环atomic-IOPS 主瓶颈适用场景开源状态
FaRM单版本MN严重经典 RDMA OCC 教学/对照闭源
FORD单版本MN严重短 OLTP, TPC-C
MotorMVCCMN仍严重(写)混合 OLTP/OLAP
LOTUS(沿 Motor)CNreactive shard rebalance(100ms)缓解中等长事务 + 漂移负载部分开源
AdaptX(沿 Motor/LOTUS)CNtwo control loops, 5ms缓解 + 限流极端 hotspot + 漂移负载✅(CREST patch)
对照:DrTM混合MN(HTM 加速)atomic 用 HTM同机柜 + Intel HTM 硬件部分

design space 上的几个洞察:

  • 数据面(版本模型 + 锁位置)在 FORD → Motor → LOTUS 走完了一圈
  • LOTUS 引入”反馈”是控制面的萌芽,但只一个环路、100ms 反应、未抽象
  • AdaptX 把这条线提到框架层,让后续工作可以按同一接口加更多环路

9. Abort 模式与失败场景汇总

读论文时常碰到”Abort”这个词,但 abort 有多种触发原因——理解这些有助于看懂 retry storm:

Abort 触发发生阶段系统响应
取锁失败(CAS 不为 0)Lock phase释放已持锁,重试
Validate 阶段 version 变Validate phase释放所有锁,重试
Backup 写超时Commit phase标记事务失败
跨 CN 协议超时(LOTUS)Lock phase重试 / 降级到 leader-CN local
Loop A 限流(AdaptX)入队阶段(其实不是 abort)等下一个 tick
MR 错误 / RDMA 异常任意 RDMA op系统级恢复

9.1 Retry storm 的形成

Worker 1: 事务开始 → CAS 成功 → 业务读 → ...
Worker 2: 事务开始 → CAS 失败(被 W1 锁了) → abort → retry
Worker 3: 事务开始 → CAS 失败(被 W1 锁了) → abort → retry
Worker 4: ... 同上 ...
...
Worker 1: commit 完释放 → 大量 retry 同时再 CAS
              → 又只一个成功,其他全 abort
              → atomic IOPS 占满, 所有 worker 反复打转
              → thpt 崩盘

这就是 retry storm 的产生。AdaptX Loop A 的核心动机就是阻断这个循环。

9.2 与 Optimistic 假设的关系

OCC 的”乐观”假设是冲突少——大部分事务一次过、少数 retry。hotspot 场景违背这个假设——本质上是 OCC 不适合的 regime。

🌟 这就是为什么 AdaptX 提”控制面”——承认 OCC 不是普适最优,在不友好的 regime 用 admission control 把它救回来

10. DM 事务系统的开放问题

读完前面几个系统,留下了哪些开放问题值得做研究/工程?

10.1 Per-key admission

AdaptX Loop A 的 admission control 是每 worker 粒度的——所有事务一视同仁。但 alt-extreme regime 暴露了一个问题:当多个 hotspot 形状不一(2 个 92% vs 1 个 95%)时,全局放行率失效

frontier 方向:per-key 信号驱动的 admission——记录每个热 key 的 abort 来源,精确限流到这条 key 而不是整个 worker。

具体子问题:

  • per-key 状态怎么不爆内存(只跟踪 top-N 热 key)?
  • 信号怎么收集(每次 abort 标注 key)?
  • 决策怎么不损害冷 key 的吞吐?

10.2 CXL pool 上的 OCC

如果 MN 是 CXL pool 而不是普通 RDMA 服务器,atomic op 的语义就完全变了——CXL.mem 的 load/store 是硬件一致的,不需要 CAS verbs。OCC 协议怎么重设计?

frontier 方向:hybrid OCC——同机柜走 CXL load/store,跨机柜走 RDMA verbs,两套协议在一个事务内组合。

具体子问题:

  • CXL load/store 的原子性保证(单 cache-line 内)够不够替代 CAS?
  • Validate 阶段怎么跨 CXL/RDMA 边界做?
  • Failure domain 重新定义(CXL 同机柜 vs RDMA 跨 region)

10.3 MVCC backup 用作 read-replica

Motor 的 CVT 给每条 record 留 K 个版本——这些老版本有没有可能被多个 CN “并行读”?如果 backup MN 上有同样的 CVT,老版本天然是 read-only 副本,可以做 read scaling。

frontier 方向:leaderless read scaling on MVCC——读流量按版本时间戳路由到任意 backup,只 primary 处理写。

具体子问题:

  • Stale read 的可接受窗口由谁定义?
  • Backup 之间不一致怎么修(也是 leader 推送,还是 backup-to-backup 协议)?
  • 跟 AdaptX Loop B(NIC IOPS-aware replica read)是同一思路的不同切入点

10.4 多控制环路的形式化合成

AdaptX 提出了 ⟨S, A, R, C⟩ 的 composition contract,但多于两个环路时怎么 composability?有没有控制论意义上的可证收敛?

frontier 方向:借鉴**控制论 / SDN(Onix、Maestro 的精神)**做形式化,给”控制面 DM 系统”画一个全局稳定性边界。

具体子问题:

  • 怎么形式化定义”signal disjoint”的充分条件?
  • 多环路同时震荡(每个都在自己的 signal 上调)的判别条件?
  • 收敛到稳定 admission point 的 Lyapunov 函数?

10.5 SmartNIC offload

ConnectX-7 + Bluefield-3 SmartNIC 提供了 NIC 内嵌 ARM 核——能不能把 OCC 的部分逻辑下放到 NIC?比如 validate 阶段在 NIC 端做,绕开 CN-MN 一次往返?

frontier 方向:NIC-side OCC validate

挑战:NIC 内核很弱(几 GB SRAM 不到、CPU 几个 ARM 核),协议要重新设计。

11. 自己读论文的 checklist

读 DM 事务相关论文时,按这个 checklist 走:

  • 物理设定:CN/MN 配置如何?网卡代际?
  • 数据布局:record 在 MN 内存的字节级布局图?
  • OCC 三阶段:read/validate/commit 各自几次 RDMA op?
  • 锁的位置:在 MN 还是 CN?用什么 op 取锁?
  • 复制策略:同步 backup commit 还是异步?
  • GC:版本回收、log truncate 怎么做?
  • 失败模式:abort 怎么触发、retry 怎么走?
  • 实验对照:跟 FaRM/FORD/Motor 比?用什么 benchmark(TPC-C/TATP/SmallBank/YCSB)?
  • 数据点:thpt/latency 数字 vs baseline 多少倍?
  • 创新归属:这篇论文的 Δ 是哪一格(版本模型/锁位置/反馈环)?

🌟 跑一遍这个 checklist,新论文你就能 5 分钟分类、20 分钟读懂关键创新


✅ 自我检验清单

  • OCC 三阶段:能默写 read / validate / commit 各阶段做的事
  • CN/MN 拆分:能讲清为什么 RDMA 让 CN/MN 分离比 2PL/2PC 更自然
  • atomic-IOPS 瓶颈:能讲清这是所有 DM 事务系统的核心难点,以及它的硬件根因
  • FORD 核心:能用一句话讲清 FORD 相比 FaRM 多解决了什么(cache-line 对齐 + doorbell batch)
  • FORD record 布局:能徒手画出 lock+version+data 的 cache-line 布局
  • FORD commit 步骤:能列出 lock/validate/write 三阶段各自的 RDMA op
  • Motor MVCC:能讲清 consecutive version table 怎么避免遍历版本链
  • Motor snapshot read:能讲清”一次 RDMA READ 拿全 K 个版本”
  • LOTUS 锁分离:能讲清”锁迁到 CN”如何绕开 atomic-IOPS 瓶颈
  • LOTUS 100ms 反应:能讲清反应式 rebalance 的触发与代价
  • AdaptX 控制面:能默写 4-tuple ⟨S, A, R, C⟩,以及 Loop A 在哪个 regime 上 1.91×
  • AdaptX AIMD math:能写出 admission_rate 的更新规则(α=0.5, δ=4)
  • 横向 design space:任意给一个系统名,能在矩阵里指出位置(版本/锁/反馈环)
  • Abort 模式:能列出 OCC 系统的 4-5 种 abort 触发原因
  • 开放问题:能列出至少 3 个 DM 事务的 frontier 方向

📚 参考资料

关键论文(必读,按时间顺序)

  • FaRM: Fast Remote Memory(Dragojević et al., NSDI’14):USENIX 链接 —— 历史奠基,所有 RDMA OCC 的”祖宗”
  • FaSST: Fast, Scalable and Simple Distributed Transactions with Two-sided RDMA Datagram RPCs(Kalia et al., OSDI’16):对照组,two-sided RPC 路线
  • DrTM: Fast In-Memory Transaction Processing using RDMA and HTM(Wei et al., SOSP’15):HTM + RDMA 混合 OCC —— 硬件辅助路径
  • NAM-DB(Zamanian et al., VLDB’17):NAM 架构,disaggregation 早期实证
  • Eris: Coordination-Free Consistent Transactions(Li et al., SOSP’17):协调免除的事务,与 OCC 路线对照
  • FORD(Zhang et al., FAST’22):USENIX 链接 —— 单版本 + cache-line 锁 + doorbell batch ⭐
  • Motor: Enabling Multi-Versioning for Distributed Transactions on Disaggregated Memory(Wu et al., OSDI’24):USENIX 链接 —— MVCC + CVT ⭐
  • LOTUS(2025):lock 分离 + reactive rebalance —— 控制面思想的雏形
  • AdaptX: A Closed-Loop Control Plane for Disaggregated-Memory Transactions(2026,本系列) ⭐:控制面 4-tuple 抽象 + 5ms 反馈环

行业对照

  • Polar / Aurora 的 RDMA 演进:工业云数据库的 RDMA 落地路径(对照学习)
  • Spanner / CockroachDB:全球分布式事务,跟 DM 事务是不同尺度的对照

行业讨论

  • USENIX 历年 DB+RDMA panel:每届 OSDI / NSDI 都会有相关 BoF
  • Carnegie Mellon 15-721 高级数据库系统(Andy Pavlo)讲义中关于 RDMA-OCC 的章节
  • Database Internals(Alex Petrov)第 3 部分关于分布式事务

经典 OCC / 并发控制基础

  • On Optimistic Methods for Concurrency Control(Kung & Robinson, 1981):OCC 协议奠基论文,40+ 年历史
  • Concurrency Control and Recovery in Database Systems(Bernstein et al., 1987):并发控制圣经

框架文档

  • CREST(Capability for RDMA-Enabled System Testing):本系列实验载体,RDMA 事务实验框架,FORD 风格 OCC + Motor MVCC 集成
  • Motor 开源仓库 —— 可作 Motor 协议代码学习

下一章切换视角,看 AI 推理领域怎么把同一套 disaggregation 思想用到 KV-cache 上。