传统 socket 通信的每一次收发都要经过内核:数据从用户态拷到内核,协议栈逐层处理,再从内核拷回对端用户态。当网络带宽进入 100G、400G,CPU 光在「搬数据」上就耗尽了——这就是 RDMA 要解决的问题。它让网卡直接读写对端内存,把 CPU 从数据搬运中解放出来。
本文从 RDMA 的动机讲起,梳理 InfiniBand 与 RoCE 的实现路径、QP 与内存注册机制、RoCE 赖以生存的无损网络(PFC + DCQCN)、verbs 编程模型,最后落到部署实践与排错。
一、RDMA 的动机与核心价值
1.1 从 socket 到 RDMA
socket 的性能瓶颈不在网络,而在主机侧:内存拷贝、系统调用、中断、协议栈处理。RDMA 把整个数据通路下沉到网卡,应用只提交「命令」,网卡自己去对端内存读写。
socket 的一次收发(主机侧成本):
用户态 → 内核拷贝 → 协议栈处理 → 网卡 DMA
→ 网络 → 对端网卡 DMA → 协议栈 → 内核 → 用户态拷贝
成本:2 次内存拷贝 + 系统调用 + 中断 + 上下文切换
RDMA 的一次收发:
应用提交 WQE → 网卡读本地内存 → 直接写对端内存
→ 对端网卡写内存 → 生成完成事件
成本:几乎零 CPU 参与,无拷贝,无系统调用(数据面)
1.2 RDMA 的三大语义
RDMA 提供三类操作语义,覆盖了从「内存访问」到「消息传递」的全部需求。理解这三者,就理解了 RDMA 的编程模型。
| 语义 | 操作 | 对端是否感知 | 典型用途 |
|---|---|---|---|
| 双边(Two-sided) | Send / Recv | 感知,需预先投递接收缓冲 | 控制消息、RPC |
| 单边写(One-sided Write) | RDMA Write | 不感知,直接写内存 | 大数据传输、KV 存储 |
| 单边读(One-sided Read) | RDMA Read | 不感知,直接读内存 | 远程读取、参数拉取 |
| 原子操作 | Compare-and-Swap 等 | 不感知 | 分布式锁、计数器 |
一句话:单边操作是 RDMA 的灵魂——对端 CPU 完全不知道数据被读写了。
二、RDMA 的实现路径
2.1 InfiniBand、RoCE 与 iWARP
RDMA 有三种落地方式:原生的 InfiniBand 专用网络、跑在以太网上的 RoCE、以及跑在 TCP 上的 iWARP。三者的差异集中在「底层承载」与「对网络的要求」上。
三种实现路径:
InfiniBand(IB):
- 专用链路层与交换机,原生无损
- 性能最好,成本最高,生态相对封闭
- 超算与 AI 训练集群的主力
RoCE(RDMA over Converged Ethernet):
- 在以太网上承载 RDMA,复用现有网络
- 需要无损网络(PFC)与拥塞控制(DCQCN)
- 数据中心最主流的选择
iWARP:
- 在 TCP 上承载 RDMA
- 无需无损网络,但性能与生态较弱
- 多用于广域网或兼容性场景
2.2 RoCEv1 与 RoCEv2
RoCE 有两个版本,差别在于封装层级:v1 直接封在以太网二层(需要二层可达),v2 封在 UDP/IP 之上(可路由,是事实标准)。生产环境几乎都用 v2。
RoCEv1(二层):
Ethernet | EtherType 0x8915 | IB Transport | Payload
限制:同一二层域,无法跨三层路由
RoCEv2(三层,事实标准):
Ethernet | IP | UDP (dst 4791) | IB Transport | Payload
优点:可路由,能跨 Leaf-Spine 甚至跨机房
注意:目的端口固定 4791,可用于识别与 QoS 标记
三、队列对与内存注册
3.1 QP、CQ 与 WQE
RDMA 的数据面围绕「队列」构建:应用把工作请求(WQE)投递到发送队列,网卡执行后把完成事件写进完成队列(CQ)。一对发送/接收队列构成一个 QP,它是 RDMA 通信的端点。
核心对象:
QP(Queue Pair):Send Queue + Receive Queue,通信端点
WQE(Work Request):应用提交的一条命令(读/写/发送)
CQE(Completion):网卡写回的完成事件
CQ(Completion Queue):完成事件的集合
连接建立后,双方 QP 互知,可直接操作对端内存
QP 类型:
RC(Reliable Connection):可靠、面向连接,最常用
UC(Unreliable Connection):不可靠连接
UD(Unreliable Datagram):不可靠数据报,支持一对多
3.2 内存注册与 MR
RDMA 网卡要直接读写应用内存,必须先把内存「注册」成 MR(Memory Region):锁定物理页(防止换出),并向网卡登记地址映射与访问权限。注册有成本,所以通常注册大块内存反复使用。
内存注册(ibv_reg_mem)做了什么:
1. 锁定物理页(pin pages),防止被换出
2. 建立虚拟地址 → 物理地址 → 网卡可用地址的映射
3. 生成 lkey(本地访问密钥)与 rkey(远程访问密钥)
4. 设置访问权限(本地读/写、远程读/写)
要点:
- 注册开销大,注册一次、复用多次
- 用 hugepage 减少页表项,提升注册与访问效率
- rkey 泄露 = 对端可任意读写该内存,安全上要严控
- 通过 ibv_reg_mr 与 ibv_dereg_mr 成对管理生命周期
四、RoCE 的无损网络要求
4.1 PFC 与优先级流控
RoCE 假设「网络不丢包」:丢包意味着重传,而 RDMA 的重传代价极高。但以太网默认是「尽力而为」,所以需要 PFC(Priority Flow Control)在链路上按优先级做流控,把拥塞转化为暂停而非丢包。
PFC(802.1Qbb)的工作方式:
- 把流量映射到 8 个优先级(RoCE 通常用优先级 3)
- 某优先级队列快满时,向对端发 Pause 帧
- 对端暂停该优先级的发送,直到收到 Resume
无损网络的代价:
1. 暂停会传播,可能引发「拥塞扩散」
2. 极端情况出现「PFC 风暴」甚至死锁
3. 因此必须配合 ECN/DCQCN 做端到端限速
4.2 ECN 与 DCQCN 拥塞控制
只靠 PFC 是危险的:它把压力从链路转移成了暂停,处理不当会造成整网停顿。DCQCN 用 ECN 标记做端到端反馈:交换机在队列将满时标记 ECN,接收端把拥塞通知回传给发送端,发送端主动降速。
DCQCN(Data Center Quantized Congestion Notification):
1. 交换机队列超过阈值 → 给报文打 ECN 标记
2. 接收端收到带标记的报文 → 生成 CNP 拥塞通知包
3. 发送端收到 CNP → 按比例降低发送速率
4. 一段时间无拥塞 → 缓慢恢复速率
三层配合(缺一不可):
端到端:DCQCN 主动限速,避免进入拥塞
链路级:PFC 兜底,极端时暂停而非丢包
监控:PFC Pause 帧计数、ECN 标记计数、CNP 计数
五、编程接口与典型用法
5.1 verbs 编程模型
RDMA 用户态编程基于 verbs API:建立连接(交换 QP 信息)→ 注册内存 → 投递请求 → 轮询完成。控制面走带外通道(TCP/socket)交换 QP 号与 rkey,数据面才走 RDMA。
verbs 编程的基本步骤:
1. ibv_get_device_list 获取 RDMA 设备
2. ibv_open_device 打开设备,创建 PD(保护域)
3. ibv_alloc_pd 分配保护域
4. ibv_create_cq 创建完成队列
5. ibv_create_qp 创建 QP
6. ibv_reg_mr 注册内存区域,拿到 lkey/rkey
7. 交换 QP 信息(带外,如 TCP)
8. ibv_modify_qp 状态迁移 INIT → RTR → RTS
9. ibv_post_send / post_recv 投递请求
10. ibv_poll_cq 轮询完成事件
5.2 一个简单的 RDMA 发送示例
下面用伪代码展示一次 RDMA Write 的关键调用,重点在「提交 WQE」与「轮询 CQE」这两步——它们都在用户态完成,没有系统调用。
/* 伪代码:一次 RDMA Write 的关键步骤 */
struct ibv_sge sge = {
.addr = (uintptr_t)local_buf,
.length = len,
.lkey = mr->lkey, /* 本地访问密钥 */
};
struct ibv_send_wr wr = {
.opcode = IBV_WR_RDMA_WRITE,
.sg_list = &sge,
.num_sge = 1,
.wr.rdma.remote_addr = remote_addr, /* 对端内存地址 */
.wr.rdma.rkey = remote_rkey, /* 对端访问密钥 */
.send_flags = IBV_SEND_SIGNALED,
};
struct ibv_send_wr *bad;
ibv_post_send(qp, &wr, &bad); /* 提交,用户态,无系统调用 */
/* 轮询完成队列,确认发送完成 */
struct ibv_wc wc;
while (ibv_poll_cq(cq, 1, &wc) == 0) { /* spin */ }
if (wc.status != IBV_WC_SUCCESS) {
/* 处理错误:wc.status 给出失败原因 */
}
六、性能与部署实践
6.1 性能指标与基准
RDMA 的价值体现在三组数字:带宽、时延、CPU 占用。评估时不能只看带宽峰值,尾时延与 CPU 节省才是 RDMA 真正的杀手锏。
关键性能指标:
带宽:单 QP 通常 10~20 Gbps,多 QP 才能打满 100G/400G
时延:单程 1~3 微秒(对比 TCP 的数十微秒)
CPU 占用:接近零(数据面不经过 CPU)
PPS:小消息场景看 IOPS,大消息场景看带宽
常用基准工具:
ib_write_bw / ib_read_bw / ib_send_bw # 带宽
ib_write_lat / ib_read_lat # 时延
perftest 工具集默认跑的是 RDMA 语义
注意:单 QP 打不满高带宽网卡,需多 QP 并发
6.2 部署要点
部署 RoCE 需要在网卡、交换机与应用三层同时配置:网卡上启用 PFC 与 ECN,交换机上配置无损队列与 DSCP 映射,应用上正确设置 MTU 与 QP 数量。
# 查看 RDMA 设备
ibv_devices
rdma link show
# 查看端口状态与速率
ibstat
ibv_devinfo
# 网卡侧:设置 RoCE 的 MTU 与流量类别
cma_roce_mode -d mlx5_0 -p 1 -m 2 # RoCEv2
# 交换机侧需配置:
# - PFC 使能于 RoCE 优先级(通常 3)
# - ECN 阈值(WRED/ECN 标记)
# - DSCP 到优先级的映射(RoCEv2 用 DSCP 标记)
# 关键:先确认整条路径的无损配置一致,再压测
七、常见坑与排错
7.1 常见坑与对策
| 现象 | 原因 | 对策 |
|---|---|---|
| 带宽远低于线速 | 单 QP 受限 | 增加 QP 数并发 |
| 时延抖动大 | PFC 暂停频繁 | 调 DCQCN 参数、查拥塞源 |
| 整网停顿 | PFC 风暴/死锁 | 收紧 PFC 触发阈值,启用 ECN |
| 连接建不起来 | QP 状态迁移错误 | 核对 INIT/RTR/RTS 参数 |
| 偶发重传 | 网络丢包(无损被破坏) | 全链路核对 PFC 配置 |
| 内存注册失败 | 超过 locked memory 上限 | 调 ulimit -l 或用 hugepage |
7.2 排错工具
排错时先看「计数器」,再看「配置」,最后才看「应用」。RDMA 网卡提供大量硬件计数器,PFC/ECN/重传异常几乎都能从计数器里读出来。
# 网卡侧计数器(PFC、ECN、重传)
ethtool -S eth0 | grep -E 'pause|ecn|cnp|discard'
# 关注:rx_pause、tx_pause、rx_ecn_marked、out_of_sequence
# RDMA 设备计数器
perfquery -x 1 mlx5_0 # 查看端口计数器
# 连接与 QP 状态
ibv_rc_pingpong -d mlx5_0 # 连通性测试
rdma link show # 链路状态与类型
# 排查顺序:
# 1. 物理链路速率与误码(ethtool、ibstat)
# 2. PFC/ECN 计数器是否异常
# 3. 端到端无损配置是否一致
# 4. 应用 QP 数与内存注册是否合理
八、总结
| 主题 | 核心知识点 | 落地建议 |
|---|---|---|
| 动机 | 摆脱内核拷贝与 CPU 搬运 | 高带宽、低时延场景才值得 |
| 语义 | 双边 + 单边读写 + 原子 | 大数据走单边,控制走双边 |
| 路径 | IB / RoCE / iWARP | 数据中心优先 RoCEv2 |
| 机制 | QP + WQE + MR 注册 | 内存注册一次复用多次 |
| 无损 | PFC 兜底 + DCQCN 限速 | 二者缺一不可,全链路一致 |
| 排错 | 先看硬件计数器 | PFC/ECN/重传是三大信号 |
RDMA 的本质是把网络从「CPU 的负担」变成「网卡的副业」:数据面完全下沉到硬件,CPU 只在控制面参与。但它不是免费的——RoCE 要求整张网络变成无损网络,PFC 与 DCQCN 的配置复杂度、PFC 风暴的风险、以及跨团队(网络、存储、应用)的协同,都是落地时的真实门槛。对后端工程师来说,RDMA 正从超算走进日常:分布式存储、AI 训练、高性能 KV 都在用它。理解 QP、内存注册与无损网络,就是理解下一代数据中心数据面的入场券——带宽的下一战,不在链路,而在主机侧。
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。