操作系统调优:内核参数、中断亲和性、CPU隔离与独占

说到操作系统调优,我见过太多团队把精力全花在代码层面,结果延迟死活降不下来。其实很多时候,瓶颈根本不在你的代码里,而在操作系统这个「管家」身上。它忙着调度线程、处理中断、切换上下文,你的交易信号就在这些「杂务」里被耽误了。

我个人习惯,拿到一台新机器,第一件事不是装软件,而是先做系统调优。今天我们就聊聊三个核心维度:内核参数、中断亲和性、CPU隔离与独占。

内核参数调优:让操作系统「让路」

Linux 内核默认是为通用场景设计的。它要照顾数据库、Web 服务器、桌面应用……唯独没考虑过微秒级交易的需求。所以我们要手动改一些参数,告诉内核:「别管那些花里胡哨的,给我让出最快的路。」

核心思路:减少内核干预,降低上下文切换,优先保障用户态程序。

我常用的几个关键参数,直接上配置:

# /etc/sysctl.conf 追加以下内容

# 减少 swap 使用,避免内存换出导致的延迟抖动
vm.swappiness = 1

# 扩大接收/发送缓冲区,防止突发流量丢包
net.core.rmem_max = 134217728
net.core.wmem_max = 134217728

# 启用 TCP 快速打开,减少握手延迟
net.ipv4.tcp_fastopen = 3

# 关闭 TCP 时间戳,减少 CPU 开销
net.ipv4.tcp_timestamps = 0

# 减少 TIME_WAIT 数量,避免端口耗尽
net.ipv4.tcp_tw_reuse = 1

# 调整内核调度器,优先低延迟
kernel.sched_min_granularity_ns = 1000000
kernel.sched_wakeup_granularity_ns = 500000

这里我特别想提一下 swappiness。曾经有个项目,延迟偶尔会突然飙升到几十毫秒,查了半天发现是内存紧张,内核把交易进程的部分内存换到磁盘了。设成 1 之后,问题再没出现过。说白了,交易系统里,内存就是命,别让内核乱动。

小技巧:改完参数后,用 sysctl -p 立即生效。但建议先在一台非生产机器上验证,别上来就改生产环境。

中断亲和性:把中断绑到指定 CPU

网卡中断来了,内核会随机选一个 CPU 去处理。如果你的交易线程刚好在那个 CPU 上运行,就会被中断打断——这就是延迟抖动的常见来源。

解决办法?把中断绑定到特定的 CPU 上,让交易线程跑在「干净」的核上。

具体怎么做?我一般分三步:

  1. 找到网卡中断号cat /proc/interrupts | grep eth0
  2. 查看当前亲和性cat /proc/irq/<中断号>/smp_affinity
  3. 设置亲和性echo 1 > /proc/irq/<中断号>/smp_affinity(将中断绑定到 CPU0)

举个例子,假设你的机器有 8 个核(0-7),交易线程跑在核 2-7 上,那你可以把网卡中断绑到核 0 和核 1:

# 将中断绑定到 CPU0 和 CPU1(位掩码 0x03)
echo 3 > /proc/irq/<中断号>/smp_affinity

我曾经在一个高频交易项目中,只做了这一步,平均延迟就降了 15%。你想想看,中断不再抢 CPU 时间,交易线程自然跑得更顺。

注意:有些网卡驱动支持多队列(RSS),每个队列有独立的中断号。这种情况下,你可以把不同队列的中断绑定到不同 CPU,实现负载均衡。但记住,交易线程所在的核,最好别绑任何中断。

CPU 隔离与独占:给交易线程一个「专属跑道」

这是最狠的一招。把某些 CPU 核从内核调度器中「摘」出来,只运行你指定的用户态程序。内核的线程、中断、定时器……统统不许碰这些核。

怎么做?用内核启动参数 isolcpus

# 在 GRUB 配置中追加
isolcpus=2,3,4,5,6,7

这样核 2-7 就被隔离了。普通进程默认不会跑上去,只有你明确用 tasksetsched_setaffinity 绑定的线程才能用。

但光隔离还不够,还要配合 rcu_nocbsnohz_full

isolcpus=2,3,4,5,6,7 nohz_full=2,3,4,5,6,7 rcu_nocbs=2,3,4,5,6,7
  • nohz_full:关闭隔离核上的定时器中断,减少周期性打扰
  • rcu_nocbs:把 RCU 回调从隔离核上移走,避免后台任务干扰

嗯,这里要注意。隔离之后,你的交易线程必须手动绑定到这些核上。我习惯用 pthread_setaffinity_np 在代码里绑定,启动时也用 taskset 做双重保险。

实战效果:在我参与的一个期权做市项目中,CPU 隔离后,延迟抖动从 ±20μs 降到了 ±3μs。效果立竿见影。

知识体系总览

下面这张图,是我自己梳理的操作系统调优核心逻辑。你可以把它当作一个检查清单:

操作系统调优核心逻辑 内核参数调优 中断亲和性 CPU隔离与独占 关键参数 • swappiness = 1 • tcp_fastopen = 3 • sched_min_granularity 绑定策略 • 中断号确认 • smp_affinity 设置 • 多队列 RSS 分配 隔离参数 • isolcpus • nohz_full • rcu_nocbs 最终目标 微秒级稳定延迟 · 零抖动

避坑指南

最后分享几个我踩过的坑:

  • 别把所有核都隔离:至少留 1-2 个核给操作系统和中断处理,否则系统可能卡死。我曾经留了 0 号核给系统,其他全隔离,运行了半年没出问题。
  • 隔离后要验证:用 htoppidstat 确认没有其他进程跑到隔离核上。有一次我发现 kswapd 偷偷跑上去了,查了半天是内核参数没配全。
  • 中断亲和性要持久化/proc 下的配置重启就丢了。建议写到 /etc/rc.local 或 systemd 服务里,开机自动设置。

操作系统调优这件事,说白了就是「抢资源」。把 CPU、内存、中断这些有限资源,尽可能多地分配给交易线程。你做得越彻底,延迟就越稳定。

我的建议:先从内核参数和中断亲和性入手,这两步改动小、见效快。如果还不够,再上 CPU 隔离。别一上来就搞大动作,容易翻车。


公众号:蓝海资料掘金营,微信deep3321