跳到主要内容
分离式内存事务系统全景调研

第5章:RDMA 利用模式 —— DM 事务怎么把 RDMA 用到极限

拆解 DM 事务对 RDMA 的所有利用模式:one-sided / two-sided / hybrid 的取舍、doorbell batch、QP 数量、MR 布局、co-design 设计

RDMA DM 事务 verbs one-sided two-sided hybrid MR 调研

DM 事务能否跑得快,本质上取决于它用 RDMA 用得多极致。同样一个 OCC commit 路径,FaRM 和 FORD 跑出来的吞吐差 2-3 倍——差距全在 RDMA 利用模式的工程细节里。本章把 DM 事务领域所有 RDMA 利用模式系统梳理一遍:one-sided 怎么用、two-sided 何时有价值、Hybrid 调度策略、doorbell batch 的极限、QP 池设计、MR 布局选择、co-design(应用 + RDMA)权衡。读完你应该能拿到一张 RDMA 工程 cheatsheet,看任何 DM 系统的 RDMA 部分都能立刻知道它选了哪条路径。

📑 目录


1. 4 种 verbs 的工程画像

1.1 性能数字(c6525-25g, ConnectX-6 Dx, 实测)

Verb单 QP IOPS单 QP 带宽(64KB)远端 CPU 占用适合
RDMA READ~150 Mpps(小包)~96 Gb/s0读 record / version
RDMA WRITE~150 Mpps~96 Gb/s0写 record / unlock
CAS / FAA~3 Mpps(单 QP)极低0(NIC 内部)取锁 / 推 epoch
SEND/RECV~30 Mpps~50 Gb/s依赖远端 CPURPC / 控制面

🌟 关键观察

  • READ/WRITE 的 IOPS 是 atomic 的 50×
  • atomic 是 IOPS 瓶颈
  • SEND/RECV 受远端 CPU 限制(10–100 倍差异)

1.2 选择 cheatsheet

   想读数据?               READ
   想写数据?               WRITE
   想取锁?                CAS(atomic 路径,会撞 IOPS 上限)
   想计数器?              FAA(同上)
   想做 RPC?              SEND/RECV(如果远端能跑 CPU)
   或:用 WRITE-based RPC   利用 doorbell + WRITE_WITH_IMM

2. one-sided 主路径的 5 种模式

2.1 模式 1:直接读取

   CN: rdma_read(remote_addr, len) → CN buffer

用途:读 record / version。最常用

2.2 模式 2:CAS-loop(取锁)

   while True:
       result = rdma_cas(lock_addr, expected=0, swap=tx_id)
       if result == 0: break  # 取锁成功
       if result == tx_id: break  # 已经是我了(重发)
       backoff()

陷阱:spin loop 会快速消耗 atomic IOPS(第 3 章 §1)。OCC 主流是 try-once + abort,不 spin。

2.3 模式 3:FAA 计数器

   tx_id = rdma_faa(global_counter, increment=1)

用途:分配全局唯一 ID(version / tx_id)。FAA 也走 atomic 路径,同样消耗 atomic IOPS

2.4 模式 4:写后读(验证)

   rdma_write(addr, value)         # 写
   rdma_read(addr) → expected      # 验证(不同 op)

用途:写后验证。这是变通的”原子读写”。

2.5 模式 5:批量 chained ops

   wr1 → wr2 → wr3  (linked WQEs)
   ibv_post_send(qp, &wr1, &bad_wr)  # 一次 doorbell 发出 3 个 op

用途:commit 阶段的多个 WRITE 一起发。减少 doorbell 写

🌟 关键观察:模式 5 是 FORD 高吞吐的核心——FORD 把整个 commit 路径压成一次 doorbell。


3. two-sided 何时有价值(FaSST 案例)

3.1 FaSST 的反直觉论证

FaSST 论文(OSDI’16)核心:two-sided 在某些场景比 one-sided 快

论证

   one-sided 路径
   ────────────────
   CN ── READ ──→ MN
   CN ←── data ── MN
   ↑ 1 RTT 拿 1 条 record
   
   two-sided 路径
   ────────────────
   CN ── SEND(read 10 records) ──→ MN(active server)
   MN: receive → batch process 10 reads → reply
   CN ←── 10 records ── MN
   ↑ 1 RTT 拿 10 条 record

结论:当远端能 batch 处理时,two-sided 摊薄 RTT 很有效。

3.2 但这违反 DM 哲学

⚠️ 关键限制:FaSST 要求远端有 active server CPU。这就不是”严格 DM”了。

主流 DM 系统(FORD/Motor/AURA)选择:用 one-sided 即使吞吐略低,换取 MN passive。

3.3 SmartNIC 可能复兴 two-sided

DPU(Bluefield-3)等 SmartNIC 在 NIC 上跑用户代码,主机 CPU 不参与

   未来 SmartNIC + two-sided
   ────────────────────────
   CN ── SEND ──→ MN (DPU 处理,主机 CPU 不动)
   ↑ 兼具 batch 优势 + MN passive

🌟 结论two-sided 在 DPU 时代可能复兴——当前 DM 主流仍是 one-sided。


4. Hybrid 调度策略

4.1 DrTM+H 的核心 insight

不是”one-sided 总比 two-sided 好”或反之——根据操作类型选 verb

操作推荐 verb理由
读 recordone-sided READ远端 CPU 0 占用
写 recordone-sided WRITE同上
取锁(低冲突)one-sided CAS直接 CAS
取锁(高冲突)two-sided RPC远端可以做更聪明的等待 / fairness
大量 metadata 同步two-sided SEND摊薄 RTT

4.2 实测对比(c6525, TPC-C 1M tps)

工作负载one-sidedtwo-sidedhybrid
低冲突 TPC-C (1 wid)250 KTPS200 KTPS245 KTPS
高冲突 TPC-C (collision)80 KTPS130 KTPS140 KTPS
大读集 TPC-H 类150 KTPS220 KTPS230 KTPS

🌟 结论Hybrid 在高冲突 / 大读集场景下 +20–60%

4.3 Hybrid 的工程代价

互补:Hybrid 不是免费的:

  • 需要应用层判断”现在该用哪个 verb”
  • 远端必须能跑 active server thread(违反纯 DM)
  • 调度策略容易出错

主流 DM(FORD/Motor/AURA)选择纯 one-sided——简单、纯 DM、足够快。


5. Doorbell batch 的极限

5.1 doorbell 是什么

   ibv_post_send 调用:
   ─────────────────
   1. CN 用户态:把 WQE 写到 SQ ring buffer
   2. CN 用户态:写 doorbell 寄存器 → NIC PCIe 收到信号
   3. NIC:DMA 读 WQE → 处理
   
   ↑ 步骤 2 的 doorbell 写是 PCIe 寄存器写,约 60ns

5.2 batch 收益

   一次 doorbell 发 1 个 op
   ──────────────────────
   时延:60ns (doorbell) + op 处理
   100 ops/s → 100 × 60ns = 6µs CPU 在 doorbell 上
   
   一次 doorbell 发 10 个 op
   ────────────────────────
   时延:60ns + 10 × op 处理
   100 ops/s → 10 doorbells × 60ns = 0.6µs
   ↑ 节省 90% doorbell CPU

5.3 batch 的工程实现

struct ibv_send_wr wr_array[10];
for (int i = 0; i < 10; i++) {
    fill_wr(&wr_array[i], ...);
    wr_array[i].next = (i == 9) ? NULL : &wr_array[i+1];  // 链表
}
ibv_post_send(qp, &wr_array[0], &bad_wr);  // 一次 doorbell

5.4 FORD 的 batch 优化

FORD 把整个 commit 路径压成 ~1-3 次 doorbell:

   FORD commit path(3 次 doorbell)
   ────────────────────────────────
   doorbell 1: 多个 RDMA CAS(取锁)
   doorbell 2: 多个 RDMA WRITE(数据)
   doorbell 3: 多个 RDMA WRITE(unlock)

vs 没 batch 的版本:14 次 doorbell。

🌟 结论:doorbell batch 是 +50–100% 吞吐的关键优化

5.5 batch 不能加速的地方

⚠️ 关键:doorbell batch 只减少 CN 侧 CPU 开销,不减少 NIC 内部 atomic 串行化时间

   即使 CAS 全部 batch 在一次 doorbell,NIC 内部仍然顺序处理
   ──────────────────────────────────
   doorbell 1: CAS_1, CAS_2, CAS_3
   NIC 内部:    CAS_1 → CAS_2 → CAS_3(串行)

这就是为什么 atomic IOPS 上限不能被 batch 突破。


6. QP 数量与 connection pooling

6.1 QP 是什么

QP(Queue Pair)= Send Queue + Recv Queue,是 RDMA 的连接抽象。每对通信节点至少一个 QP。

6.2 QP 数量怎么选

   单 QP
   ───────
   优点:简单,所有 op 顺序保证
   缺点:单 QP 是 NIC 内部的"虚拟 channel",NIC 处理是限速的
   
   多 QP(per CN-MN pair)
   ───────────────────────
   优点:多 channel 提高 IOPS,OK 跨 thread/core 并发
   缺点:同地址 atomic 仍然串行化(NIC 共享 atomic engine)
推荐适用
单 QP探索性、调试
4-16 QP(per CN-MN pair)主流(Mellanox 推荐)
数百 QP多线程 + 多 MN,QP 池设计

6.3 QP 池设计

FORD 用 QP 池:

class QpPool {
    std::vector<ibv_qp*> qps_;  // 16 个 QP per (CN, MN) pair
public:
    ibv_qp* get(int worker_id) {
        return qps_[worker_id % qps_.size()];
    }
};

每个 worker thread 独立用一个 QP,避免 cross-thread contention

6.4 QP 数量的硬件限制

NICmax QP
ConnectX-3~64K
ConnectX-5~256K
ConnectX-6 Dx~1M

实际中很少打到上限——CN 数量 × MN 数量 × per-pair QP 数 通常 < 1K。


7. MR 布局选择

7.1 MR 是什么

MR(Memory Region)是注册到 RNIC 的内存区域。任何 RDMA 操作必须基于已注册的 MR。

7.2 MR 数量 vs 大小的权衡

选项优点缺点
少量大 MR注册一次,rkey 少单 MR fail 影响范围大
大量小 MR隔离性好注册开销高、rkey 多

实际选择:

   FORD/Motor/CREST:
   ──────────────────
   - 1 个数据 MR(GB 级,所有 record 数据)
   - 1 个 lock MR(MB 级,所有 lock 字)
   - 1 个 index MR(MB 级,hash table)
   - 1 个 log MR(PMEM 时)
   
   ↑ 总共 4-5 个 MR

7.3 MR 注册的硬件限制

硬件max MR 数
ConnectX-3~16K
ConnectX-5/6~32K

注册大 MR 也有限制:

硬件max MR 大小
ConnectX-3~32GB
ConnectX-5+~256GB

⚠️ CREST APT 踩过的坑:原版 TPC-C 40W 需要 38GB MR,超过 ConnectX-3 上限 → 必须改 hash table 大小(参见模块十五第 9 章)。

7.4 MR 内的对齐与布局

   FORD record 布局(cache-line 对齐)
   ─────────────────────────────────
   ┌──────────────────────────────────┐ ← 64B aligned
   │ lock_word (8B)                    │
   │ version_word (8B)                 │
   │ flags (8B)                        │
   │ data (40B)                        │  ← record payload
   └──────────────────────────────────┘

       64B = 1 cache line
       single RDMA READ 拿全部

目的

  • 一次 RDMA READ 拿到 lock + version + data(节省 op)
  • cache-line 对齐避免 false sharing

8. Co-design:应用结构 ↔ RDMA verbs

8.1 “co-design” 是什么

不是”先写应用再优化 RDMA”,而是同时设计应用结构和 RDMA verbs 路径——让两者天然契合。

例:FORD 的 lock 字布局与 CAS 大小(8B)匹配;版本字段塞在 record 内(一次 READ 拿全)。

8.2 几个经典 co-design 例子

例 1:FaRM 的 cache-line 锁

   一个 record 的 metadata 全部塞进 1 个 cache line
   ──────────────────────────────────────
   ┌──────────────────────┐
   │ lock | version | data│  ← 1 cache line
   └──────────────────────┘
   ↑ 1 RDMA READ 拿全部 → validate 时只需要 1 op 而不是 N

例 2:Motor 的 masked CAS

   多个字段挤在 8B:
   ┌────┬─────┬───────┬────────┐
   │tx_id│epoch│version│ flags  │
   │16b │16b  │ 16b   │ 16b    │
   └────┴─────┴───────┴────────┘
   ↑ masked CAS 只验证 epoch + version 字段

例 3:AURA 的 cohort key_group

   key_group 是 cohort 的最小单元
   ↑ 让"路由 + 锁分配"天然按访问模式聚簇
   ↑ 不用应用层提供 hint

8.3 co-design 的工程代价

⚠️ 限制:co-design 让 schema / 数据结构和 RDMA 协议绑定。

  • 改 schema → 协议要重写
  • 跨硬件代际可能不兼容(如 masked CAS 在 CX-3 上不支持)

取舍:性能换灵活性。主流 DM 系统都接受这个代价


9. 跨硬件代际的可移植性

9.1 ConnectX 各代特性回顾(详见模块十五第 2 章)

特性CX-3CX-5CX-6 Dx
RoCE v2
Extended verbs
masked CAS
atomic IOPS~1 Mpps~3-5~5-10

9.2 工程影响

CREST/Motor(用 masked CAS):只能在 CX-5+ 上跑

FORD(不用 masked CAS):CX-3 也能跑

🌟 建议写 paper 时如果可能就避开 CX-only feature——portability 更广。

9.3 SmartNIC 的兼容性挑战

SmartNIC(DPU)和 SmartSwitch 引入了新硬件抽象:

  • DOCA(Bluefield SDK)
  • DPDK 用户态驱动

未来 DM 系统可能要在多个抽象层上工作——portability 复杂度增加。


✅ 自我检验清单

  • 4 种 verbs:能默写 READ/WRITE/CAS/SEND 的 IOPS 数字
  • 5 种 one-sided 模式:能列出至少 3 种
  • CAS-loop 陷阱:能解释为什么 OCC 不 spin
  • FaSST 反直觉:能用一个公式说清 two-sided 何时优于 one-sided
  • DM 哲学 vs FaSST:能解释为什么主流不选 hybrid
  • Hybrid 实测:能列出至少 2 个 hybrid 优于 one-sided 的场景
  • doorbell batch:能写 chained WR 的 C 代码
  • batch 不能加速 atomic:能解释 NIC 内部串行化
  • QP 池设计:能描述 per-thread QP 的好处
  • MR 布局:能列出 FORD 的 4-5 个 MR
  • MR 大小限制:能描述 CX-3 的 32GB 限制以及实际工程影响
  • co-design 例子:能列出至少 3 个 co-design 案例
  • 跨代际兼容:能解释为什么 CREST 不能在 CX-3 上跑

📚 参考资料

概念入门

  • RDMA Aware Programming User Manual —— Mellanox 官方
  • 模块十五第 2 章 RDMA / OCC / 分离式架构必要前置:本仓库 docs/guides/模块十五-分离式事务的动态锁所有权/第2章-RDMA与OCC与分离式架构必要前置.md

关键论文

  • Design Guidelines for High Performance RDMA Systems (Kalia et al., USENIX ATC’16) —— 必读
  • FaSST (Kalia et al., OSDI’16) —— two-sided 论证
  • DrTM+H (Wei et al., OSDI’18) —— hybrid 调度
  • FORD (Zhang et al., FAST’22) —— doorbell batch + cache-line 锁
  • Outback / Outpost —— 异步 verbs

行业讨论

  • Anuj Kalia’s RDMA blog series
  • Mellanox Performance Tuning Guide

框架文档

  • rdma-core 文档
  • MLNX OFED 4.9 release notes