TL;DR
- 撮合系统的端到端预算往往只有 ~100μs;但 TCP/IP(Socket)每跳常见就吃掉 20–50μs,原因主要不是“网线慢”,而是内核网络栈的拷贝、syscall、协议处理与中断带来的固定开销和不确定性。
- RDMA 的两把刀:Kernel Bypass(数据路径不走内核)+ Zero-Copy(网卡直接从/向用户态内存 DMA),让节点间通信更接近“内存语义”。
- 落地优先级别搞反会失败:不要一上来“全链路 RDMA”。先抓最值钱的两条链路:定序器→撮合引擎的订单分发,以及撮合主→备的状态复制(经典对口:RDMA Write)。
- RDMA 不是银弹:你会用“成本/复杂度”换“微秒级确定性”。要为内存注册、CPU 绑核忙轮询、无损网络(RoCE)配置和应用层容错付出工程代价。
1) 为什么 TCP/IP 在撮合关键路径上总像一堵墙?
在交易系统里,“网络延迟”的大头经常来自操作系统:
用户态 buffer 需要拷贝到内核 Socket buffer,协议栈要跑 TCP 状态机/校验/分段,
还会触发 syscall、上下文切换与中断处理。
这些开销不仅贵,而且带来抖动(尾延迟),会把撮合引擎原本可预测的热路径打碎。
关键要点 / 常见坑(工程视角)
- 只盯“带宽”不盯“延迟构成”:10/25/100GbE 解决不了 syscall/协议栈/拷贝的固定成本;低延迟先算预算,再看每一跳的“可解释时间”。
- 把 TCP 调参当成终局:Nagle、IRQ Affinity、busy poll、SO_REUSEPORT…能优化,但对微秒级目标通常只是“缓解”,不是“破局”。
- 误把“平均延迟”当 KPI:撮合更关心 P99/P999;内核中断与调度抖动常常体现在尾部。
2) RDMA 的核心:绕开内核,直达内存
RDMA(Remote Direct Memory Access)的目标是让数据从发送方用户态内存到接收方用户态内存,
尽量少让 CPU/内核参与。
常见的 Verbs 组件包括:QP(Queue Pair)、CQ(Completion Queue)、以及内存注册(MR)。
在极致低延迟场景里,CQ 通常采用专用核忙轮询,用 100% CPU 换走中断/唤醒的不可预测成本。
3) 架构改造抓“生命线”:分发 + 主备复制
比较务实的切入方式是把外部接入层(面向大量连接、跨公网)继续留在 TCP;
把撮合集群内部两条关键路径换成 RDMA:
- 定序器 → 撮合引擎:用 Send/Receive 做高效消息通道,减少每笔订单在网络层的固定开销。
- 撮合主 → 备:用 RDMA Write 做状态日志复制;远端 CPU 几乎不介入,天然适配“同步复制决定交易延迟”的场景。
落地时最容易踩的几个坑
- 运行时频繁 ibv_reg_mr:内存注册会 pin 物理页,开销可达微秒级;正确做法是启动时预分配 + 预注册内存池,运行期只做指针切分/复用。
- RoCE 没配成“无损以太网”:PFC/ECN/队列与拥塞配置缺失,会导致丢包 → 性能断崖式下跌,定位成本高;InfiniBand 更可预测但设备成本更高。
- 把“RDMA 可靠连接 = 系统可靠”:RC 只保证链路语义,节点宕机/分区/重连仍要应用层做日志、重放与状态恢复。
- 忽略流控:One-sided Write 很快,但如果发送端不做节制,可能把接收端内存写爆;需要 credit/水位/批处理等手段。
适用场景
- HFT/交易所撮合内核:对“每微秒都值钱”的业务,愿意为确定性投入硬件与工程复杂度。
- 主备同步复制成为延迟瓶颈:复制延迟直接叠加到每笔交易;RDMA Write 往往能显著压缩这段成本。
- 同机房/同可用区的低延迟 RPC/消息总线:当 gRPC/Kafka 的跳数与内核成本不可接受时,RDMA 更对口。