RDMA基础回顾:RDMA工作原理、关键概念与TCP/IP对比

在深入RDMA性能基准测试之前,必须先厘清RDMA的核心机制。很多性能调优的误区,根源在于对RDMA“零拷贝”“内核旁路”等特性理解得过于笼统。本节将聚焦RDMA的工作流程、三个最关键的概念(QP、CQ、MR),并与传统TCP/IP协议栈做结构化对比,为后续的基准测试指标解读和瓶颈定位打下基础。

2.1 RDMA工作原理:从“拷贝四次”到“直达应用缓冲区”

传统TCP/IP网络收发的数据路径,数据从网卡到应用需要经过内核协议栈处理,并伴随多次内存拷贝。RDMA(Remote Direct Memory Access)的核心设计目标,是让网卡(RNIC,RDMA Network Interface Card)绕过内核,直接读写对端应用预先注册好的内存区域。其数据通路可以概括为以下三个关键动作:

  1. 内存注册(MR Registration):通信前,两端应用将自己要用于收发数据的内存缓冲区注册到RNIC,并获取该内存区域的物理地址映射和访问密钥(rkey/lkey)。RNIC后续的DMA操作只能访问这些已注册的内存。
  2. 请求下发(Post Send/Recv):应用通过驱动将“发送描述符”或“接收描述符”投递到网卡的发送队列(SQ)或接收队列(RQ)中。描述符中包含了数据所在的内存地址、长度以及远端内存的访问信息。
  3. 硬件DMA搬运:RNIC从SQ中取出描述符,直接通过PCIe总线DMA读取本地内存中的数据,并封装成数据包发送到网络。接收端RNIC收到数据后,根据数据包中的目的QPN和PSN,将数据直接DMA写入对端预先注册好的接收缓冲区中,整个过程无需CPU参与数据搬运。
关键认知:RDMA的本质是“网卡硬件直接访问应用内存”,而不是“更快的TCP”。它消除了内核协议栈的参与,从而大幅降低了延迟和CPU占用率。
发送端应用 内存缓冲区 (MR) 发送端RNIC SQ / RQ 队列 接收端应用 内存缓冲区 (MR) 接收端RNIC SQ / RQ 队列 RDMA 网络 (InfiniBand/RoCE) DMA读 (CPU不参与) DMA写 (CPU不参与) 数据包 数据包 Post Send/Recv Post Recv CQ通知 CQ通知 与传统TCP/IP的关键差异: • TCP/IP:数据经过内核协议栈,经历多次拷贝(内核缓冲区→用户缓冲区),CPU参与校验和、内存拷贝。 • RDMA:RNIC直接DMA读写应用内存,CPU仅负责下发描述符和处理完成事件,不参与数据搬运。 • 结果:延迟降低一个数量级(微秒级),CPU占用率大幅下降,带宽利用率更高。

2.2 三大核心概念:QP、CQ、MR

RDMA编程模型中,QP、CQ、MR是理解一切操作的基础。它们之间的关系可以类比为:MR是“仓库”(内存区域),QP是“传送带”(通信队列),CQ是“完成状态看板”(通知机制)。

2.2.1 QP(Queue Pair,队列对)

QP是RDMA通信的基本实体,由发送队列(SQ)和接收队列(RQ)组成。每个QP都有一个唯一的QPN(Queue Pair Number),用于网络数据包的路由识别。QP支持多种传输类型:

  • RC(Reliable Connection,可靠连接):面向连接,提供可靠传输、乱序重排、重传机制,类似TCP。绝大多数RDMA应用(如存储、数据库)使用RC。
  • UC(Unreliable Connection,不可靠连接):面向连接但不可靠,无重传,适合对丢包不敏感的高性能场景。
  • UD(Unreliable Datagram,不可靠数据报):无连接,类似UDP,支持多播,但报文长度受限(通常不超过MTU)。

2.2.2 CQ(Completion Queue,完成队列)

CQ用于通知应用其先前提交的发送/接收请求(WR,Work Request)是否已完成。当RNIC完成一个WR的处理(成功或失败),会生成一个CQE(Completion Queue Entry)放入CQ中。应用通过轮询(Poll CQ)或事件通知(Event Notification)的方式获取CQE,从而释放缓冲区并判断操作结果。

性能提示:在基准测试中,CQ的轮询方式直接影响测试结果。使用ibv_poll_cq忙轮询(Busy Polling)可以获得最低延迟,但会占满一个CPU核心;使用事件通知则延迟更高但CPU占用低。测试时需明确记录轮询模式。

2.2.3 MR(Memory Region,内存区域)

MR是应用注册给RNIC可访问的内存区域。注册时需要指定内存地址、长度和访问权限(本地读/写、远端读/写)。RNIC会为每个MR分配一个lkey(本地密钥)和rkey(远端密钥)。远端访问时,必须持有rkey才能对该MR进行RDMA读写操作。MR的注册和注销是有开销的,因此高性能应用通常采用内存池方式,预先注册大块MR并复用。

概念作用关键属性性能影响
QP通信队列,承载收发请求QPN、传输类型(RC/UC/UD)、队列深度队列深度过小会限制吞吐;RC类型重传开销较大
CQ完成通知机制CQ深度、轮询/事件模式轮询模式延迟低但CPU占用高;CQ过浅会导致丢完成事件
MR内存注册区域lkey/rkey、访问权限、内存地址注册/注销开销大;建议复用MR

2.3 与传统TCP/IP的对比:为什么RDMA更快?

为了直观理解RDMA的性能优势,我们从数据路径和CPU参与度两个维度进行对比。以下是一个典型的TCP/IP发送流程与RDMA发送流程的步骤对比:

TCP/IP发送路径(以loopback或跨机为例):
应用调用send() → 数据从用户缓冲区拷贝到内核socket缓冲区
→ 内核TCP/IP协议栈处理(校验和、分段、路由)
→ 网卡驱动将数据从内核缓冲区DMA到网卡
→ 网卡发送数据包
接收端:网卡接收 → DMA到内核缓冲区 → 内核协议栈处理
→ 数据从内核缓冲区拷贝到用户接收缓冲区 → 应用recv()返回
RDMA发送路径:
应用注册MR → 构造WR(包含内存地址、长度、远端rkey)
→ 调用ibv_post_send()将WR投递到SQ
→ RNIC硬件DMA读取本地MR数据 → 封装并发送
接收端:RNIC硬件根据数据包中的QPN和rkey
→ DMA直接写入对端预先注册的MR → 生成CQE → 应用轮询CQ获取完成

从上述对比可以看出,RDMA省去了两次内核内存拷贝和内核协议栈处理。在TCP/IP路径中,CPU不仅要执行校验和计算,还要参与数据在用户态与内核态之间的多次拷贝。而RDMA路径中,CPU只负责“下发指令”和“接收完成通知”,数据搬运完全由硬件完成。

2.4 常见误区与复盘

误区一:认为RDMA就是“更快的TCP”,可以直接替换。
RDMA的API模型(verbs)与socket API完全不同。它要求应用自行管理内存注册、QP状态机、完成队列轮询等。直接将TCP程序替换为RDMA而不修改应用逻辑,无法发挥性能优势,甚至可能因错误使用导致性能下降。
误区二:忽略MR注册的开销。
在基准测试中,如果每次发送都临时注册/注销MR,会导致严重的性能瓶颈。正确的做法是预先注册一块大内存池,将缓冲区切分复用。测试代码中应区分“MR注册开销”和“纯数据传输开销”。
误区三:混淆“轮询模式”与“事件模式”的测试结果。
使用ibv_poll_cq忙轮询时,CPU占用率接近100%,但延迟最低;使用ibv_req_notify_cq事件通知时,CPU占用低但延迟可能增加数微秒。在对比不同测试工具或不同实现时,必须确认CQ的消费方式是否一致,否则数据不可比。

2.5 本节小结