第四章:网络协议栈:从TCP到UDP,再到RDMA与内核旁路技术

做量化交易的朋友,尤其是搞高频的,一定对网络延迟又爱又恨。我刚开始入行那会儿,总觉得代码写得够快就行了,网络嘛,交给操作系统不就好了?结果被现实狠狠教育了一顿。

今天咱们聊聊网络协议栈。说白了,就是数据从你的交易程序发出去,到交易所服务器收到,中间经历了什么。这条路,走法不同,延迟天差地别。

4.1 TCP:可靠但慢,为什么?

TCP,传输控制协议。它最大的特点就是可靠。你发一个包,对方必须回一个ACK确认。没收到?重传。这保证了数据不丢、不乱序。

但代价呢?延迟。

我举个例子。你在交易系统里发一个订单,TCP会先建立连接——三次握手。你想想看,光是握手就多了一个RTT(往返时间)。在微秒级的世界里,这简直是灾难。

还有更坑的:TCP的拥塞控制。网络稍微有点抖动,它自动降低发送速率。你这边行情正猛,它给你来个慢启动……嗯,我遇到过,那感觉就像赛车手在直道上被踩了刹车。

核心问题: TCP的可靠性是用延迟换来的。对于高频交易,我们宁愿丢几个包,也不愿等。

4.2 UDP:快,但你要自己兜底

UDP就简单粗暴了。它不管对方收没收到,只管发。没有握手,没有拥塞控制,没有重传。延迟极低。

但问题来了:丢包怎么办?

我个人的习惯是:在应用层自己做可靠性。比如,每个UDP包加一个序列号。接收方发现序号跳了,就知道丢了包。至于要不要重传,看业务场景。

对于行情数据,丢了就丢了,下一笔马上来。对于订单,必须保证送达,那就自己实现一个轻量级的确认机制。

避坑指南: 我曾经在UDP上直接跑订单流,结果网络抖动丢了一个包,订单没发出去,但本地以为成功了。后来我加了一个应用层ACK,延迟只多了几百纳秒,但可靠性上来了。

4.3 内核旁路:绕过操作系统

不管是TCP还是UDP,数据都要经过操作系统内核。内核负责协议栈处理、数据拷贝、上下文切换。这些操作,每一个都是延迟的元凶。

你想想看,你的交易程序在用户态,网卡在内核态。数据从网卡到应用程序,要经过:

  1. 网卡收到数据,触发中断
  2. 内核处理中断,拷贝数据到内核缓冲区
  3. 内核协议栈处理(TCP/UDP头部解析)
  4. 内核把数据拷贝到用户态缓冲区
  5. 系统调用返回,你的程序才能读到数据

这一套下来,几百纳秒到几微秒就没了。对于高频交易,这太奢侈了。

所以有了内核旁路技术。说白了,就是让应用程序直接和网卡对话,跳过内核。

4.4 RDMA:远程直接内存访问

RDMA,Remote Direct Memory Access。它允许一台机器的应用程序直接读写另一台机器的内存,而不需要经过双方的CPU和操作系统。

怎么做到的?

网卡上有个专门的硬件,叫RNIC(RDMA网卡)。它自己处理协议栈,直接和应用程序的内存交互。数据从网卡到应用内存,零拷贝,零内核参与。

我做过一个测试:同样的数据量,TCP延迟大约10微秒,RDMA可以做到1微秒以内。差距是数量级的。

关键点: RDMA的核心是“卸载”。把协议处理从CPU卸载到网卡硬件上,把数据拷贝从内核卸载到硬件DMA。

4.5 几种技术的对比

技术 延迟(典型值) CPU占用 可靠性 适用场景
TCP 10-50 μs 非高频交易、管理通道
UDP 1-5 μs 低(需应用层保证) 行情数据、低延迟信号
内核旁路(如DPDK) 0.5-2 μs 高频交易、极速行情
RDMA 0.5-1 μs 极低 高(硬件保证) 极速交易、内存数据同步

4.6 知识体系图

下面这张图,展示了从传统TCP到RDMA的演进路径,以及各层级的延迟瓶颈。

网络协议栈演进与延迟瓶颈 TCP 协议栈 内核协议处理 数据拷贝(内核→用户) 系统调用/上下文切换 UDP 协议栈 内核协议处理(轻量) 数据拷贝(内核→用户) 系统调用/上下文切换 DPDK / 内核旁路 用户态驱动 零拷贝(网卡→用户) 无系统调用 延迟:10-50 μs 延迟:1-5 μs 延迟:0.5-2 μs 演进方向:TCP → UDP → 内核旁路 → RDMA(延迟递减,复杂度递增) 核心瓶颈:内核协议处理 + 数据拷贝 + 系统调用

4.7 实际选型建议

说了这么多,到底怎么选?我个人的经验是这样的:

  • 管理通道、风控、清算:用TCP。稳定第一,延迟无所谓。
  • 行情接收:用UDP。丢几个包没关系,下一笔马上来。但要做好应用层的丢包检测和补偿。
  • 极速交易:上内核旁路或RDMA。我目前在用的就是DPDK + 用户态协议栈,延迟稳定在1微秒以内。
注意: RDMA虽然快,但部署成本高。需要专门的网卡(Mellanox、Intel等),而且交换机也要支持。如果你的交易量不大,或者交易所不支持,DPDK是更现实的选择。

嗯,网络协议栈这块,说白了就是“用硬件换时间”。你愿意花多少钱买硬件,决定了你能把延迟压到多低。但不管怎么选,理解底层原理,才能做出正确的取舍。

一个小技巧: 如果你刚开始做低延迟,别一上来就上RDMA。先用UDP + 应用层优化,把延迟压到5微秒以内。然后看看瓶颈在哪,再决定要不要上内核旁路。一步到位容易翻车。

专注资料整理