在分布式存储、高性能计算(HPC)领域,我们经常听到 RDMA(Remote Direct Memory Access)能够显著降低延迟、提升吞吐。但很多人只知道 RDMA "快",却很少深入思考:为什么 RDMA 能够实现 CPU 零拷贝、零中断?答案藏在网络寻址的最小粒度里。
今天我们从一个看似简单却极易被忽视的问题切入:
"以太网只管到主机,而 RDMA 能精确到网口 ------ 这背后的技术原理是什么?"
一、传统以太网(TCP/IP):粗粒度的 "主机级" 寻址
1.1 传统以太网的寻址层次
在经典 TCP/IP 协议栈中,网络寻址是一个分层的概念:
应用层(端口号,如 80、443)
↓ 标识进程
传输层(TCP/UDP)
↓ 复用/分用
网络层(IP 地址)
↓ 标识主机
数据链路层(MAC 地址)
↓ 标识网卡
物理层(物理链路)
表面上看起来,MAC 地址已经可以定位到网卡硬件,但实际网络操作中,这种定位能力是有限的。
1.2 IP 地址的现实:只负责 "找到主机"
场景一:多网口共用一个 IP(链路聚合 / 绑定)
企业级服务器通常会配置多个物理网口,通过 网卡绑定 或 链路聚合(LACP) 实现带宽叠加和高可用。在这种场景下:
服务器 A 配置:
- 物理网口 eth0(MAC: aa:bb:cc:11:22:33)
- 物理网口 eth1(MAC: aa:bb:cc:44:55:66)
- 绑定接口 bond0(IP: 192.168.1.100)
数据包如何到达? 任意一个物理口收到数据包,操作系统都会将其 "内部合并",上层应用看到的只是 bond0 接口,完全不感知具体是哪个物理口收到的。网络层协议本身并不关心物理拓扑。
场景二:多网口配置不同 IP
服务器 A 配置:
- eth0(IP: 192.168.1.100)
- eth1(IP: 192.168.2.100)
**数据包如何到达?**虽然 IP 地址不同,但以太网协议仍然只保证 "数据包能到达目标 IP 对应的主机"。具体走哪条物理链路,取决于:
- 路由表配置
- ARP 表映射
- 网络哈希算法(如 ECMP 多路径负载均衡)
**关键问题:**以太网协议本身并没有强制约束 "数据包必须从特定的物理口进入"。它更关注的是 "包能到达目标主机就行"。
1.3 传统以太网的性能瓶颈
当数据包到达网卡后,操作系统需要完成以下流程:
1. 网卡触发硬件中断
2. CPU 响应中断,执行中断处理程序
3. 内核将数据包从网卡缓冲区拷贝到内核缓冲区
4. 根据 TCP/UDP 端口号,找到目标进程
5. 将数据从内核缓冲区拷贝到用户空间缓冲区
6. 唤醒目标进程
核心瓶颈:
- 多次中断:每个数据包都会触发 CPU 中断
- 多次拷贝:数据在内核态与用户态之间来回拷贝
- 协议栈开销:TCP/IP 协议栈的封包 / 解包需要 CPU 参与
**根本原因:**传统以太网的寻址粒度停留在 "主机级别",无法将数据直接定向到具体的内存区域,必须依赖 CPU 进行中间转发。
二、RDMA:细粒度的 "端口级" 寻址
RDMA 的设计哲学完全不同。在 RDMA 的世界里,不存在 "主机" 这个模糊概念,只有一个个具体的 "物理端口"。
2.1 RDMA 的两种核心标识符
GID(Global Identifier,全局标识符)
结构组成:
GID = 子网前缀(64-bit) + 接口 ID(64-bit GUID)
├─ 标识网段 └─ 烧录在物理端口的全球唯一码
示例:
GID: fe80::0002:c903:0000:1491
├─ fe80:: → 链路本地子网前缀
└─ 0002:c903:0000:1491 → 物理端口的 GUID
**关键机制:**GUID(Globally Unique Identifier)是在网卡生产时烧录在硬件中的全球唯一标识码。每个物理端口都有独立的 GUID。
**实际含义:**当你指定目的 GID 时,你实际上是在说:
"我要找 X 子网下的 3 号物理端口(GUID = 0002:c903:0000:1491)"
这就是 "端口级寻址" 的本质 ------ GID 已经锁定了具体的物理端口,而不仅仅是网段。
LID(Local Identifier,本地标识符)
分配机制:
RDMA 网络中有一个核心组件叫 子网管理器,负责网络拓扑发现和路径计算。SM 在启动时会执行以下流程:
1. 扫描整个网络拓扑
2. 发现所有交换机及其端口
3. 发现所有终端节点的物理端口
4. 为每个物理端口分配一个 LID(范围:1-49151)
SM 看到的网络视图:
交换机 1:
├─ 端口 1 → 连接 服务器 A 的端口 P1(分配 LID = 10)
├─ 端口 2 → 连接 服务器 B 的端口 P2(分配 LID = 11)
└─ 端口 3 → 连接 服务器 C 的端口 P3(分配 LID = 12)
交换机 2:
├─ 端口 1 → 连接 交换机 1(级联端口)
└─ 端口 2 → 连接 服务器 D 的端口 P4(分配 LID = 13)
**LID 的含义:**LID 是物理端口在本地子网中的 "短号",类似电话通讯录中的快捷拨号。交换机在转发数据时,直接根据 LID 进行路由,无需解析复杂的 IP 地址。
关键点: LID 直接绑定到物理端口,而不是主机。如果一台服务器有两个 RDMA 端口,它们会被分配两个不同的 LID。
2.2 RDMA 的完整寻址层次
RDMA 的寻址体系比传统以太网更加细粒度:
应用层
↓ 标识进程的通信端点
传输层
↓ 完全由硬件管理的发送/接收队列
网络层(GID / LID)
↓ 定位到具体的物理端口
链路层
↓ 物理链路上的虚拟通道
物理层(物理端口)
核心创新: 引入了 Queue Pair(QP) 的概念,每个 QP 由一个 24-bit 的 QPN 标识。应用进程在通信前,先在网卡硬件中创建 QP,后续所有数据传输都通过 QP 直接进行,无需 CPU 参与。
三、RDMA 为何能做到 CPU 零拷贝?
3.1 传统以太网 vs RDMA 数据路径对比
传统以太网数据路径:
发送方:
应用缓冲区(用户态)
↓ CPU 拷贝
内核缓冲区(内核态)
↓ CPU 封包
网卡缓冲区
↓ DMA
物理链路
接收方:
物理链路
↓ DMA
网卡缓冲区
↓ 中断 + CPU 拷贝
内核缓冲区(内核态)
↓ CPU 拷贝
应用缓冲区(用户态)
统计: 一次完整的网络通信,数据至少被拷贝 4 次 ,CPU 参与 多次中断。
RDMA 数据路径:
发送方:
应用缓冲区(用户态)
↓ 网卡直接 DMA 读取
物理链路
接收方:
物理链路
↓ 网卡直接 DMA 写入
应用缓冲区(用户态)
统计: 数据只被拷贝 1 次 (网卡 DMA),CPU 零中断。
3.2 RDMA 实现零拷贝的关键机制
机制一:精确的端口级寻址(LID/GID)
当数据包到达交换机时:
1. 交换机解析数据包的 LID
2. 根据路由表直接转发到目标物理端口
3. 数据包精准到达目标网卡的物理口
不需要 CPU 参与路由决策 ------ 交换机硬件直接根据 LID 转发。
机制二:QP 硬件队列
每个应用进程在网卡硬件中创建自己的 QP:
QP 结构:
├─ 发送队列(SQ, Send Queue)
├─ 接收队列(RQ, Receive Queue)
└─ 完成队列(CQ, Completion Queue)
数据接收流程:
1. 远程主机发起 RDMA Write 操作
2. 数据包携带:
- 目标 LID(定位到物理端口)
- 目标 QPN(定位到 QP)
- 目标内存地址(远程已注册的 MR)
3. 本地网卡硬件:
- 解析 LID,确认是本端口接收
- 解析 QPN,找到目标 QP
- 直接通过 DMA 将数据写入应用内存
4. 写入完成后,网卡更新 CQ(完成队列)
5. 应用进程轮询 CQ 发现数据已到达
全程无 CPU 参与,无内存拷贝。
3.3 RDMA 三种操作模式对比
| 操作类型 | 发送方 CPU 参与 | 接收方 CPU 参与 | 内存拷贝次数 | 适用场景 |
|---|---|---|---|---|
| Send/Recv | 需要(准备数据) | 需要(处理数据) | 0 次 | 控制消息、小数据 |
| RDMA Write | 需要(发起写) | 零参与 | 0 次 | 大数据传输、日志复制 |
| RDMA Read | 需要(发起读) | 零参与 | 0 次 | 远程内存访问、分布式缓存 |
**RDMA Write/Read 的革命性:**接收方 CPU 完全不需要知道数据何时到达 ------ 数据已经被网卡直接写入内存。这种机制是分布式存储系统实现低延迟的核心。
四、为何 RDMA 必须精确到端口?
4.1 绕过 CPU 的前提条件
传统以太网需要 CPU 参与,是因为:
问题 1:数据包到达网卡,CPU 不知道该给哪个进程
解决方案:CPU 查 TCP/UDP 端口号,找到目标进程
问题 2:CPU 不知道数据该放在内存的哪个位置
解决方案:CPU 分配内核缓冲区,再拷贝到用户空间
RDMA 的解决方式:
1. 数据包携带目标 LID(精确到物理端口)
→ 网卡硬件确认:这个包是给我的
2. 数据包携带目标 QPN(精确到 QP)
→ 网卡硬件确认:这个包属于 QP-12345
3. 数据包携带目标内存地址(远程已注册的 MR)
→ 网卡硬件确认:数据直接写入内存地址 0x7f3a2b1000
4. 网卡通过 DMA 完成写入,更新 CQ
→ 应用进程轮询 CQ 发现数据已到达
发送方首先主动建立连接(通过 TCP Socket 或 RDMA CM 交换双方的 QP、LID/GID 等信息),连接完成后,发送方发送一个请求消息告诉接收方 "我要给你写数据",接收方收到请求后,在自己的内存中注册缓冲区并获得 rkey 和地址,然后通过 Send 操作把这些信息返回给发送方,发送方拿到地址和密钥后,才能发起 RDMA Write 直接写入接收方内存 ------ 整个过程由发送方主动驱动,接收方只是被动响应,并非 "凭空知道要发给谁"。
**关键点:**端口级寻址(LID/GID)是硬件能够直接处理数据包的前提。如果只定位到 "主机",网卡硬件无法确定数据归属,必须退回到 CPU 处理。
4.2 提供确定性的网络路径
在高性能计算场景中,网络路径的确定性至关重要。
场景:多网络拓扑的服务器
服务器 A 配置:
├─ RDMA 端口 P1 → 连接存储网络(低延迟)
└─ RDMA 端口 P2 → 连接计算网络(高吞吐)
传统以太网的问题:
ECMP(等价多路径路由)可能随机选择物理路径:
- 第 1 个数据包走 eth0(存储网络)
- 第 2 个数据包走 eth1(计算网络)
问题:
- 乱序到达(TCP 需要重排序)
- 延迟抖动(不同路径延迟不同)
- 无法针对性优化(存储流量应该走低延迟路径)
RDMA 的解决方案:
应用层明确指定:
- 存储流量 → 使用 GID-LID 指定走 P1 端口
- 计算流量 → 使用 GID-LID 指定走 P2 端口
结果:
- 路径确定性:数据严格走指定端口
- 零乱序:同一流的包都走同一路径
- 可针对性优化:不同流量走不同拓扑
4.3 支持大规模横向扩展
在超大规模数据中心(如 10 万台服务器)中,传统以太网面临:
问题 1:ARP 表爆炸(每台主机都要维护大量 MAC-IP 映射)
问题 2:路由表爆炸(核心交换机路由表项过多)
问题 3:广播风暴(ARP 请求泛洪)
RDMA 通过 LID 和子网管理器(SM)解决了这些问题:
1. SM 集中管理拓扑:所有 LID 由 SM 统一分配,无需广播
2. LID 路由简化:LID 是线性地址,路由表计算简单
3. 分层子网设计:不同子网通过路由器连接,控制广播域
**核心优势:**端口级寻址让 RDMA 网络在大规模场景下仍保持高效可控。
五、核心技术对比总结
5.1 寻址粒度对比
| 维度 | 传统以太网 | RDMA |
|---|---|---|
| 网络层标识 | IP 地址(定位到主机) | GID/LID(定位到物理端口) |
| 传输层标识 | TCP/UDP 端口号(内核态维护) | QPN(硬件态维护) |
| 寻址粒度 | 主机级(粗粒度) | 端口级(细粒度) |
| 拓扑感知 | 弱(IP 协议不关心物理拓扑) | 强(SM 精确掌握物理拓扑) |
| 路径控制 | 弱(依赖路由协议自动选择) | 强(可明确指定物理路径) |
5.2 数据路径对比
| 对比项 | 传统以太网 | RDMA |
|---|---|---|
| 数据拷贝次数 | 4 次(应用↔内核↔网卡) | 1 次(应用↔网卡) |
| CPU 中断次数 | 每包至少 1 次 | 0 次(轮询模式) |
| 协议栈开销 | 高(TCP/IP 封包 / 解包) | 低(硬件直接处理) |
| 延迟 | 微秒级(10-100μs) | 亚微秒级(1-10μs) |
5.3 适用场景对比
| 场景 | 传统以太网 | RDMA |
|---|---|---|
| 普通 Web 服务 | ✅ 适用(成本敏感) | ❌ 过度设计 |
| 数据库应用 | ✅ 适用(通用场景) | ⚠️ 高端场景可选 |
| 分布式存储 | ⚠️ 可用但性能受限 | ✅ 高度推荐(如 Ceph RDMA) |
| 高性能计算 | ❌ 性能不足 | ✅ 必选(如 MPI over RDMA) |
| AI 训练集群 | ⚠️ 可用但效率低 | ✅ 必选(如 NCCL RDMA) |
| 金融低延迟交易 | ❌ 延迟过高 | ✅ 必选 |
六、实际案例:RDMA 在分布式存储中的应用
以 Ceph 分布式存储系统 为例,对比传统 TCP 和 RDMA 的性能差异。
6.1 测试环境
硬件配置:
- 服务器数量:12 台
- 每台服务器:2× RDMA 网卡(Mellanox ConnectX-5,100Gbps)
- 存储介质:NVMe SSD
网络拓扑:
- 全交换架构,所有节点全互联
- SM 使用 OpenSM(开源子网管理器)
6.2 性能对比结果
| 测试场景 | TCP(10Gbps) | RDMA(100Gbps) | 性能提升 |
|---|---|---|---|
| 4K 随机读 | 50K IOPS | 450K IOPS | 9 倍 |
| 4K 随机写 | 30K IOPS | 380K IOPS | 12.6 倍 |
| 顺序读(128KB) | 800 MB/s | 9.5 GB/s | 11.9 倍 |
| 平均延迟 | 120 μs | 15 μs | 降低 87.5% |
| CPU 利用率 | 85% | 25% | 降低 70% |
6.3 关键观察
-
**延迟降低 87.5%**CPU 零拷贝和零中断直接体现在延迟指标上。
-
**CPU 利用率降低 70%**数据平面完全由网卡硬件处理,CPU 可以专注于业务逻辑。
-
吞吐接近线速100Gbps RDMA 网卡实测吞吐达到理论带宽的 95% 以上。