第2章:必备底座 —— atomic IOPS 物理墙、OCC、分离式架构
读 AURA 论文前的 30 分钟知识包:ConnectX 代际差异下 atomic IOPS 为什么有物理上限、RDMA OCC 三阶段标准实现、分离式内存 vs RDMA-attached storage 边界、CREST/FORD/Motor 共享的最小抽象(Pool / Hash Index / Cell-level CC)
第 1 章把 AURA 的主张和谱系定位讲清楚之后,紧接着的问题是:读到论文 §2 motivation 时,atomic IOPS 上限的”1 Mpps / 5 Mpps”数字、OCC validation 阶段的 read-set check、CREST 的 Pool / Hash Index 抽象,这些前置概念能不能不卡? 本章把读 AURA 必须先打通的 4 个底座一次性补齐——ConnectX 代际 atomic 行为差异、RDMA OCC 三阶段标准实现、分离式内存与 RDMA storage 边界、CREST/FORD/Motor 共享的最小抽象。读完直接进入第 3 章 motivation 重读不会卡。
📑 目录
- 1. 为什么需要这一章:读论文 §2 之前要懂的 4 件事
- 2. RDMA atomic IOPS 物理墙:为什么不能水平扩
- 3. RDMA OCC 三阶段标准实现
- 4. 分离式内存边界:DM vs RDMA-attached storage vs CXL
- 5. CREST / FORD / Motor 共享的最小抽象
- 6. 把这些底座叠在一起:一张事务读路径速查图
1. 为什么需要这一章:读论文 §2 之前要懂的 4 件事
AURA 论文 §2 的 motivation chain 大致是这样:
§2.1:DM 事务里锁的获取依赖 MN 的 atomic(CAS / FAA),atomic IOPS 受 RNIC 内部串行化制约,上限是物理的。 §2.2:单纯客户端路由(把热点请求集中到一个 CN)不能减少 atomic 的 总 量,只能改变 分布。 §2.3:必须把”锁权威位置”作为一个可在线设计的物理参数对待。 §2.4:设计目标(5 条)。
这 4 段每一段都引用了一组”前提知识”:
| § | 引用的前提 | 如果不懂会怎样 |
|---|---|---|
| §2.1 | RNIC 内 atomic 单元 + PCIe 串行 | 看不懂为什么 ConnectX-3 / 6 数字差不了一个数量级 |
| §2.2 | OCC validation 失败 → retry storm | 看不懂”路由不够”的物理原因 |
| §2.3 | DM vs RDMA storage 边界 | 容易把 AURA 当成 CXL 方案 |
| §2.4 | CREST / FORD 的 Pool + Hash Index 抽象 | 看不懂”在 CREST 上实现”具体改哪里 |
本章按上面 4 个前提分 4 节讲透。
🍎 学习节奏建议:每一节都有”☝️ 看到论文里出现这个词时,回到本节”的标签,先快速通读,做后续章节遇到术语时再回查。
2. RDMA atomic IOPS 物理墙:为什么不能水平扩
☝️ 看到论文里出现:“atomic IOPS 物理上限 / RNIC 串行化 / ConnectX 代际差异”时,回到本节。
2.1 RNIC 内部 atomic 单元长什么样
RDMA 的 atomic 操作(CAS、FAA)和 READ/WRITE 不一样——它不是数据搬运,而是在 MN 的某段内存上做一次原子读改写。这需要 RNIC 上一个单 atomic 处理单元(Atomic Unit, AU)串行化处理所有 atomic 请求。
┌──────── MN side ────────┐
│ │
CN ─ atomic_req ─► RNIC ─► AU (串行处理) ─► 内存原子写
│ │
│ 其他 atomic_req 排队等 │
└──────────────────────────┘
为什么必须串行?
- PCIe 一致性:atomic 必须先把内存读到 RNIC 内部缓存、做修改、写回,整个过程要相对 MN CPU 的其他访问可线性化
- 跨 QP 一致性:多个 CN 同时发 atomic 到同一段地址,必须有全局序
- 硬件实现简化:单 AU 比多 AU + 锁简单,主流 RNIC 都这么做
🌟 结论:atomic 的吞吐上限 = AU 处理速度 × 时间窗口,不随 QP 数、CN 数水平扩。
2.2 ConnectX 代际差异(实测)
下面是模块十五第 1 章 + AURA 论文用的标准实测数字(ib_atomic_bw -F -t 4 跑 64B CAS):
| 网卡 | 上市年份 | atomic IOPS(实测) | 备注 |
|---|---|---|---|
| ConnectX-3 | 2012 | ~1 Mpps | APT cluster 同款 |
| ConnectX-3 Pro | 2014 | ~1.2 Mpps | LOTUS 同款 |
| ConnectX-4 / 5 | 2017 | ~3–4 Mpps | rdma-core 起点 |
| ConnectX-6 Dx | 2020 | ~5–10 Mpps | CloudLab c6525 同款 |
| ConnectX-7 | 2023 | 估算 ~10–15 Mpps | 未实测 |
🧠 关键洞察:11 年从 1 Mpps 涨到 10 Mpps,远低于摩尔定律或 PCIe 带宽增长——因为 AU 单元的瓶颈不是带宽,是单点延迟(PCIe round trip + 内存 atomic latency),这两个在硬件上都没本质改进空间。
2.3 为什么 batch / coalescing / outstanding 救不了
第 1 章 §3 已经讲了反直觉点,本节补具体的物理原因:
- batch 8 个 CAS 到一个 work request:硬件层仍按 8 次独立 atomic 处理,AU 不能并行执行 atomic
- coalescing 写锁请求:只能减少 client 端发送次数,不减 MN 端原子处理次数(且会引入 serialization 在 client 侧)
- 加 outstanding queue:队列堆深,延迟上升 → 端到端吞吐还是上限(Little’s Law:throughput = concurrency / latency,AU 是 throughput-bound)
🍎 直觉比喻:把 AU 想成银行总行只有一个 ATM 机的取款窗口。
- batch = 把 8 张卡装信封一起寄给银行 → 银行还是要一张一张刷
- coalescing = 让客户排好队再来 → 银行 ATM 处理速度不变
- outstanding queue = 让大家把卡都先交给银行排队 → 卡堆得越多,每张卡等的越久
🌟 结论:atomic IOPS 是物理预算。AURA 论文 §2.1 的整个论证都站在这一条上。
3. RDMA OCC 三阶段标准实现
☝️ 看到论文里出现:“OCC validation / read-set / write-set / retry”时,回到本节。
3.1 三阶段的标准时序
DM 事务系统(FaRM / FORD / Motor / CREST / AURA)全部基于 OCC,没有一家用 2PL(two-phase locking)。OCC 在 RDMA 上的标准三阶段是:
时间 ─────────────────────────────────────────────────►
[Read Phase] ─────► [Validation Phase] ──► [Commit Phase]
│ │ │
├ RDMA READ 拉数据 ├ 重新 READ 读集校验 ├ CAS / WRITE 落盘
├ 记录到 read-set │ 版本号 / lock bit ├ replicate
├ 在本地 buffer 改 ├ 失败 → abort, retry └ unlock
│ 生成 write-set │ 成功 → 进 commit │
三阶段每一阶段都对应 RDMA 操作:
| 阶段 | 操作 | 典型实现 |
|---|---|---|
| Read | 一个 RDMA READ + 一个 read-set record | one-sided READ |
| Validation | 重读 read-set 验证版本/锁状态 | one-sided READ |
| Commit | 加锁 + 写值 + 解锁 | atomic CAS + RDMA WRITE + atomic FAA |
3.2 Validation 失败 → retry storm 是怎么发生的
这是论文 §2.2 论证”路由不够”的核心:
100 个事务都想写 same record
│
├─ Read phase 都拿到 version=5
│
├─ Validation phase 全部去 CAS(version=5 → version=6)
│
├─ 第 1 个成功,剩下 99 个 CAS 失败 → version_mismatch
│
├─ 99 个 abort + retry → 又是 100 个 CAS 请求
│
└─ 形成 retry storm,**atomic IOPS 全用在 abort/retry 上**
🧠 关键洞察:retry storm 下,atomic 的有效吞吐 = AU 吞吐 / 平均 retry 次数。这是为什么”加 CN 反而更慢”的物理原因——加 CN 增加了发起 CAS 的客户端数,但 AU 上限不变。
3.3 OCC 在 AURA 里的位置
AURA 不改 OCC——三阶段还是这三个阶段,只是把 commit phase 的加锁那一步从”MN atomic CAS”换成”在 owner CN 上 OwnerLockTable 加锁”:
原版 OCC 三阶段(FORD/Motor/CREST) AURA 三阶段(local owner)
──────────────────────────────────── ───────────────────────────
[Read] RDMA READ [Read] RDMA READ
[Valid] RDMA READ [Valid] RDMA READ
[Commit] MN atomic CAS ──────► 物理墙 [Commit] OwnerLockTable 本地原子
RDMA WRITE RDMA WRITE
MN atomic FAA ───
🌟 结论:AURA 的 atomic 不是消失了,是搬到了 CN 本地——CN 上原子操作走 CPU 指令(lock cmpxchg),不经过 RNIC AU,吞吐天花板从 5 Mpps 提升到 ~100 Mpps(4 CN × 单 CN 多核)。
📎 工程踩坑视角:CREST 上的具体改造在模块十五第 4 章 + 本模块第 8 章详讲。
4. 分离式内存边界:DM vs RDMA-attached storage vs CXL
☝️ 看到论文里出现:“Disaggregated Memory / DM 事务 / CXL Pool”时,回到本节。
读 AURA 论文很容易把它当成”CXL 方案”或”RDMA storage 方案”。实际上 AURA 严格属于 **DM(Disaggregated Memory)**事务一支。三者边界:
| 维度 | DM(AURA / FORD / Motor) | RDMA storage(NVMf / IB-SRP) | CXL Pool(Pond) |
|---|---|---|---|
| 内存语义 | 字节寻址,远端 byte-addressable | 块语义(4KB / 64KB block) | 字节寻址,硬件一致性 |
| 访问原语 | RDMA verbs(READ / WRITE / CAS / FAA) | NVMe-oF protocol | load/store 指令 |
| 一致性 | 软件维护(OCC / MVCC) | 块级(block-level) | 硬件维护 |
| 典型延迟 | 2–5 μs | 50–200 μs | 200–400 ns |
| AURA 适用? | ✅ 这就是 AURA 的舞台 | ❌ 块语义没 atomic | ❌ 硬件一致性消除热点 |
🌟 结论:AURA 是为 RDMA + 字节寻址远端内存设计的事务系统。它的所有 motivation(atomic 物理墙、OCC retry storm)都基于”远端内存按 byte 寻址、原子操作走 RNIC AU”这个前提。
4.1 DM 事务的两层抽象
DM 事务系统的运行时分两层:
┌─ CN (Compute Node) ───────────────────────────────┐
│ - 应用 + 事务逻辑 │
│ - 协程调度 / 工作线程 │
│ - OCC 三阶段实现 │
│ - 本地 cache / write buffer │
└─────────────────┬──────────────────────────────────┘
│ RDMA verbs(双向 + 单向)
┌─────────────────▼──────────────────────────────────┐
│ MN (Memory Node) │
│ - 内存池(Pool) │
│ - Hash Index / Btree(FORD/Motor 数据结构) │
│ - 不跑应用逻辑(除了 atomic 的 AU 处理) │
└────────────────────────────────────────────────────┘
🧠 关键洞察:MN 不跑应用逻辑。所有”算”都在 CN 上,MN 只是被 RDMA 操纵的内存。这是 DM 和”远程 KV 服务”的本质区别。
📎 工程踩坑视角:CREST 的 MN motor_mempool 实现就是这个——它只 listen RDMA 连接 + 注册 MR,几乎没有 CPU 逻辑,CN 端完全通过 RDMA 操纵远端内存做事务。
5. CREST / FORD / Motor 共享的最小抽象
☝️ 看到论文里出现:“Pool / PoolHashIndex / Cell-level CC / masked-CAS”时,回到本节。
AURA 的实现是在 CREST 上做的,CREST 又继承了 FORD/Motor 的部分抽象。这一节把”读 AURA 实现章必须先认识的 5 个抽象”列清楚——后面 §5 / §8 章会反复用。
5.1 Pool:MN 的内存池基本单位
// 简化版(来自 src/mempool/Pool.h)
class Pool {
void* base_; // 注册 MR 的起始地址
size_t size_; // MR 总大小
PoolHashIndex* idx_; // 一个或多个 hash index 指针
// ... allocator state
};
🌟 结论:Pool 是 MN 上一段已经注册 MR 的连续内存,CN 通过 rkey + offset 用 RDMA 操纵。
5.2 PoolHashIndex:远端 hash 表
bucket[0]: ┌──────────┬──────────┬──────────┐
│ slot[0] │ slot[1] │ slot[2] │
│ key/val │ key/val │ key/val │
│ version │ version │ version │
│ lock_bit │ lock_bit │ lock_bit │
└──────────┴──────────┴──────────┘
bucket[1]: ┌──────────┬──────────┬──────────┐
│ ... │
每个 slot 是一个 cache-line 对齐的记录,包含:
- key + value
- version(OCC 用)
- lock bit / lock holder id(cell-level CC 用)
🧠 关键洞察:lock bit 在 slot 里、不在单独的 lock table 里——这是 FORD 提出的 “in-data lock”。CAS 时 mask 掉 version + value,只看 lock bit,称为 masked-CAS。AURA 的 fallback 路径走的就是这个 masked-CAS(论文 §3.x FallbackLock)。
5.3 Cell-level CC:CREST 的并发控制粒度
CREST 把锁粒度从 row 拆到 cell(单个字段)——一行有 N 个字段就有 N 个 lock bit。
record: ┌─────────┬─────────┬─────────┬─────────┐
│ field 0 │ field 1 │ field 2 │ field 3 │
│ lock=1 │ lock=0 │ lock=0 │ lock=1 │
└─────────┴─────────┴─────────┴─────────┘
🌟 结论:cell-level CC 显著降低 false conflict。AURA 不改这一层——它在 cell-level CC 之上抽象出 cohort(key_group 的集合),cohort 与 cell 是不同维度的抽象。
5.4 masked-CAS:在 64B cache line 上同时改锁 + 版本
64B cache line layout:
┌──────────┬─────────────┬──────────┬─────────┐
│ lock_bit │ version (4B)│ payload │ padding │
│ (1B) │ │ (54B) │ (5B) │
└──────────┴─────────────┴──────────┴─────────┘
CAS old: (lock=0, version=5, payload=X)
CAS new: (lock=1, version=6, payload=Y)
compare_mask: 0xFFFFFFFFFFFFFFFF (整条 line)
📎 工程踩坑视角:CREST 的 RDMA masked-CAS 必须落在 64B cache line 内,跨 line 的 CAS 不是原子的。这是 §5 实现章会反复出现的约束。
5.5 OwnerLockTable:AURA 在 CN 端加的新抽象
// 简化版(来自 src/transaction/aura/OwnerLockTable.h)
class OwnerLockTable {
std::unordered_map<KeyGroupId, LockEntry> entries_;
// 每个 entry: lock_holder, version, txn_queue
// 操作: TryAcquire / Release / Hand-off
};
🌟 结论:OwnerLockTable 是 AURA 在 CN 上加的本地锁服务——key 是 cohort 内的 key_group,value 是锁状态。本地 lock_cmpxchg 替换了 MN atomic CAS。
原来: CN ──RDMA atomic CAS──► MN AU (吞吐受限)
AURA: CN ──本地 lock_cmpxchg──► OwnerLockTable(本机 CPU)
第 4 章 / 第 5 章会展开 OwnerLockTable 的 cohort 安装、迁移协议、跨 CN OwnerRpc 慢路径。
6. 把这些底座叠在一起:一张事务读路径速查图
把本章 4 节叠成 AURA 上一个 NewOrder 事务从读取到提交的完整路径图(精简版,详细版在第 4 / 7 章):
┌─── CN ──────────────────────────────────────────────┐
│ │
│ 1. 应用决定要读 stock(w_id=2, i_id=42) │
│ │ │
│ 2. 查 OwnerLockTable: cohort owner = self? │
│ │ │
│ ├─ 是 → 本地 TryAcquire │
│ │ └─ 成功 → 拿到锁 │
│ │ │
│ └─ 否 → OwnerRpc 慢路径 → 远端 CN │
│ └─ 远端 OwnerLockTable.TryAcquire │
│ │
│ 3. RDMA READ 拉 stock record │
│ │ │
│ 4. 在本地 buffer 改值(计算 new stock) │
│ │ │
│ 5. Validation: 重读,版本一致?锁仍在? │
│ │ │
│ 6. Commit: │
│ ├─ owner local: 本地版本号 +1 + RDMA WRITE │
│ └─ fallback: masked-CAS on MN slot │
│ │
│ 7. Release lock(本地或 RPC) │
│ │
└───────────────────────────────────────────────────────┘
🧠 关键洞察:步骤 2 是 AURA 引入的新分支——根据 OwnerMap manifest 决定走本地 fast path 还是 RPC slow path。所有 §3 的算法(cohort 学习、ownership planning、affinity routing)都是为了让”是 → 本地 TryAcquire”这条分支命中率最大化。
✅ 自我检验清单
- atomic 物理墙:能解释为什么 ConnectX-3 与 ConnectX-6 atomic IOPS 只差 ~5 倍(AU 单点延迟、PCIe 串行)
- batch 反直觉:能用”银行 ATM”比喻解释为什么 batch / coalescing 不能压住 atomic 上限
- OCC 三阶段:能徒手画 Read / Validation / Commit 三阶段 + 每阶段用什么 RDMA 操作
- retry storm:能解释 OCC validation 失败为什么会形成 retry storm
- DM 边界:能区分 DM / RDMA storage / CXL Pool 三者的访问语义
- Pool / PoolHashIndex / Cell-level CC:能说出 CREST 上这三层各自的职责
- masked-CAS:能解释为什么 masked-CAS 必须落在 64B cache line 内
- OwnerLockTable:能说出 AURA 把原 MN atomic 替换成什么(本地 lock_cmpxchg)
第 3 章预告
第 3 章按论文 §2 的 motivation chain 顺序,逐段重读:
- §2.1 锁瓶颈 → 本章 §2 atomic 物理墙的论证版本
- §2.2 为什么单纯路由不够 → retry storm + 5 种 DM 锁热点对照
- §2.3 从数据物理设计到锁所有权物理设计 → MorphoSys / Lion 类比 + AURA 的代差
- §2.4 设计目标 5 条 → 每条对应后续哪个章节
读完第 3 章你能徒手把 §2 motivation 三段论复述给同行听。
📚 参考资料
关键论文 / 文档
- Mellanox ConnectX 系列 datasheet —— atomic 单元 + AU 描述(厂商 PDF)
- RDMA Aware Programming User Manual (Mellanox, 2020) —— OCC 三阶段标准实现参考
- FORD (Zhang et al., FAST’22) —— in-data lock + masked-CAS 的奠基论文:USENIX 链接
- Motor (Wu et al., OSDI’24) —— MVCC + 一致版本表:USENIX 链接
- Pond (Li et al., ASPLOS’23) —— Microsoft 云端 CXL 1.1 实测(用作 DM vs CXL 边界对照)
测量工具
- perftest 套件:
ib_atomic_bw/ib_read_bw/ib_write_bw—— Mellanox OFED 自带 - ib_atomic_bw 标准跑法:
ib_atomic_bw -F -t 4 -s 64 --report_gbits—— AURA 论文 §2.1 实测脚本
模块内交叉引用
- 模块十五第 1 章:DM 事务的 atomic IOPS 物理墙 —— 本章 §2 的实测数据展开版(含 retry storm 微观图)
- 模块十五第 2 章:RDMA 与 OCC 与分离式架构必要前置 —— 本章 §3 + §4 的工程展开版
- 模块二十第 4 章:FORD / Motor / LOTUS / AdaptX 横向 —— 本章 §5 抽象的对比版