4、网络协议栈优化:TCP vs UDP vs RDMA、内核旁路技术、零拷贝、网卡多队列与RSS

做市系统里,网络延迟就是真金白银。我见过太多团队,算法写得再漂亮,结果被网络协议栈拖了后腿。今天咱们就聊聊,怎么把这层“中间商”给优化掉。

4.1 TCP vs UDP vs RDMA:选对协议,少走弯路

先说TCP。它可靠、有序,但代价太大。三次握手、拥塞控制、ACK确认——每一个环节都在增加延迟。我在早期做做市系统时,就吃过TCP的亏。行情数据一爆发,TCP的拥塞窗口直接缩成蜗牛,订单根本送不出去。

UDP呢?无连接、无确认、无重传。说白了就是“发了就不管”。但做市场景下,行情数据丢几个包问题不大,订单却不能丢。所以UDP适合行情,不适合交易。

RDMA就厉害了。它允许一台机器的内存直接读写另一台机器的内存,完全绕过操作系统。延迟能压到1微秒以内。我曾在项目中用InfiniBand配合RDMA,把订单处理延迟从20微秒砍到3微秒。嗯,这个数字我记得很清楚。

协议 延迟(典型值) 适用场景 缺点
TCP 10-50 μs 订单、风控 拥塞控制、上下文切换
UDP 1-5 μs 行情、心跳 不可靠、需应用层处理
RDMA 1-3 μs 极速交易、内存共享 硬件成本高、配置复杂

我的建议:行情走UDP,订单走TCP,如果预算够且延迟敏感,订单链路直接上RDMA。别混用,否则调试起来你会想哭。

4.2 内核旁路技术:绕过操作系统这个“中间商”

为什么内核旁路这么重要?因为每次网络数据进来,都要经过内核协议栈——中断、拷贝、上下文切换。这一套下来,几十微秒就没了。做市系统里,这几十微秒可能就是一笔交易的盈亏。

DPDK(Data Plane Development Kit)是绕开内核的典型方案。它让用户态程序直接接管网卡,轮询收包,零中断。我在搭建行情网关时,用DPDK把收包延迟从30微秒降到了5微秒以内。代价是CPU占用高,但值。

OpenOnload是Solarflare网卡的技术,本质也是内核旁路。它更“聪明”——只加速TCP连接,不改变你的代码。我有个朋友,把交易系统从普通网卡换成Solarflare + OpenOnload,延迟直接砍半。他跟我说:“早知道这么简单,我早换了。”

避坑指南:我曾经在DPDK上踩过一个坑——忘了绑定CPU核心。结果DPDK线程和业务线程抢CPU,延迟反而更高。记住:DPDK线程必须独占核心,不能共享。

4.3 零拷贝技术:数据不动,指针动

传统网络收包,数据要从网卡→内核缓冲区→用户缓冲区,至少拷贝两次。零拷贝就是让数据只在内核和用户态之间共享内存,不搬数据。

实现方式有两种:

  • mmap + sendfile:适合文件传输,做市系统用得少。
  • DPDK的零拷贝:网卡直接把数据写入用户态内存池,应用直接读。这才是做市场景的王道。

我记得有一次优化订单处理链路,发现数据从网卡到应用走了4次拷贝。改成DPDK零拷贝后,延迟从18微秒降到了7微秒。你想想看,这还没改算法呢,只是把“搬砖”的活省了。

// 传统方式:两次拷贝
recv(sock, buf, len, 0);  // 内核→用户

// DPDK零拷贝:直接读内存池
struct rte_mbuf *mbuf = rte_pktmbuf_alloc(mempool);
// 数据已经在mbuf里,直接处理
process_packet(mbuf->data, mbuf->data_len);

注意:零拷贝不是银弹。如果数据需要频繁修改或重组,零拷贝反而增加复杂度。我的原则是:只对“读一次就丢”的数据用零拷贝,比如行情快照。

4.4 网卡多队列与RSS:让每个核心都有活干

单队列网卡有个问题:所有数据包都挤在一个队列里,一个CPU核心处理。多核CPU?浪费了。RSS(Receive Side Scaling)就是解决这个的——它根据数据包的哈希值,把不同流分配到不同队列,每个队列绑定一个CPU核心。

做市系统里,RSS特别适合行情数据。比如把不同合约的行情哈希到不同核心,每个核心独立处理。我曾在项目中用4队列网卡,把行情处理吞吐量从50万包/秒提升到200万包/秒。嗯,这个提升很直观。

配置RSS时要注意哈希算法。默认是IP+端口哈希,但做市场景下,同一个IP的不同合约可能哈希到同一个队列。我建议用自定义哈希,把合约ID也加进去。

我的经验:网卡队列数最好等于CPU物理核心数(不是超线程)。比如16核CPU,配16个队列。多了反而因为缓存竞争导致性能下降。

4.5 知识体系总览

下面这张图,是我自己梳理的优化路径。从协议选择到硬件配置,每一步都能压出几微秒。你跟着走一遍,网络延迟至少降一半。

网络协议栈优化路径 1. 协议选择 TCP(订单) → UDP(行情) → RDMA(极速链路) 2. 内核旁路 DPDK(轮询收包) → OpenOnload(加速TCP) 3. 零拷贝 DPDK内存池 → 用户态直接读 → 避免内核拷贝 4. 网卡多队列 + RSS 队列数 = 物理核心数 → 自定义哈希 → 负载均衡

这张图从左到右,从上到下,就是一条完整的优化链路。我个人习惯是:先选协议,再搞内核旁路,然后上零拷贝,最后调多队列。每一步都能看到延迟下降,很有成就感。

最后说一句:网络优化没有银弹。别一上来就上RDMA,先看看你的瓶颈在哪。我曾经见过一个团队,花大价钱上了RDMA,结果发现瓶颈在数据库。嗯,方向错了,再好的技术也白搭。

蓝海数据掘金营,专注资料整理