RDMA 与 RoCE:数据中心高性能网络、无损网络与拥塞控制

系统讲解 RDMA 与 RoCE:从 socket 到零拷贝远程内存访问的动机、InfiniBand/RoCE/iWARP 的实现路径、QP 与内存注册机制、PFC 与 DCQCN 构成的无损网络、verbs 编程模型与部署排错实践。

传统 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、内存注册与无损网络,就是理解下一代数据中心数据面的入场券——带宽的下一战,不在链路,而在主机侧。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「network」更多文章

  1. SDN 与 OpenFlow:控制与转发分离、控制器与南向接口
  2. 网络时间同步:NTP、PTP 与高精度时钟
  3. eBPF 网络数据面:XDP、tc 与可编程转发