一次Redis超时引发的“冤案“

一、问题:从一次偶发超时说起

你有没有遇到过这种情况:应用报 Redis 超时,你吭哧吭哧去查 Redis 监控、GC 日志、慢查询------结果 Redis 一切正常。再查网络、查连接数、查防火墙------也都好好的。问题在哪?不知道,反正"不是我的问题"。

今天要讲的这个 case,就遇到了同样的困惑。不过最后挖出来的根因很有意思:既不在 Redis,也不在网络,而是在 CPU 的一颗核上。

在 docker97.xxx.qihoo.net 这个节点上,部分 Pod 访问 Redis 时出现了偶发超时,具体表现为:

• 应用日志 里 Redis 请求 RT 偶发拉长,甚至直接超时

• 非持续性 ,重试后往往恢复,但时不时又冒出来

• Redis 服务端本身没有任何异常------CPU、连接数、QPS 都正常

从表象看,这不像典型的应用 Bug,也不像 Redis 性能瓶颈。更像是某种底层系统抖动。

二、验证:网络层面排除了什么

先确认网络是否真的稳定。在 Pod 网络命名空间里直接验证:

nc -z -v 10.220.193.137 25747

结果很有意思:大多数时间完全正常,少数几次连接建立明显变慢。

阶段性结论:不是典型网络链路故障。更像是节点侧处理能力不稳定。

三、转向:换个角度重新看

当 "应用无明显异常 + 网络不稳定但无硬性丢包" 同时出现时,应立刻警惕:

⚠️ CPU / 中断 / 软中断(softirq)层面的处理能力问题

尤其是 Redis 这种高频短连接、高频网络 IO 的场景,对软中断调度延迟极其敏感------数据包到了网卡,但 CPU 什么时候来处理它,这里面的不确定性就会直接转化为请求延迟。

四、深入:软中断的追凶之旅

  1. CPU 和中断全景观察

先用 mpstat 看全局 CPU 状态:

mpstat -P ALL 1

mpstat -I SCPU 1 5

发现:个别 CPU 核的 %soft(软中断占用)明显偏高,软中断在 CPU 间分布极不均匀。

再看中断分布:

cat /proc/interrupts | less -S

cat /proc/softirqs | less -S

top --> 1

进一步统计每个 CPU 的中断总量:

awk '{for(i=2;i<=NF;i++)ai+=$i} END{for(i in a)print "CPU"i-2":",ai}' /proc/interrupts

发现:网络相关 IRQ / softirq 明显集中在少数 CPU

  1. 网卡与 NUMA 拓扑关系

先确认网卡型号和 PCIe 信息:

ethtool -i eth2

driver: ixgbe

version: 5.10.134-14.an8.x86_64

firmware-version: 0x80000625

bus-info: 0000:84:00.0

#lspci -vvvs 0000:84:00.0

#查看网口绑定的NUMA node编号

cat /sys/class/net/eth2/device/numa_node

#查看网卡队列与CPU绑核关系

grep . /proc/irq/*/smp_affinity_list

查网卡挂载的 NUMA 节点:

cat /sys/class/net/eth2/device/numa_node

#确认:网卡挂载在 NUMA Node 0

关键背景 :如果中断 / 软中断跑在非本 NUMA 节点的 CPU 上,会引入远端内存访问,直接造成延迟抖动。

#用 lstopo 可以生成完整的 NUMA + PCIe 拓扑图

yum install -y hwloc hwloc-gui

生成带网卡的完整 NUMA + PCIe 拓扑图

sudo lstopo --whole-system --whole-io --rect --fontsize 9 --gridsize 8 /root/topo.svg

  1. irqbalance------这个"老好人"闯了祸

irqbalance(中断均衡服务)是 Linux 默认用来动态迁移中断的工具。它的工作逻辑是:周期性读取 /proc/interrupts,然后把中断尽量"平均地"调度到各个 CPU 上。听起来很合理对吧?

但问题来了:

在高吞吐、低延迟场景(尤其是 Redis / RPC)下,中断的"漂移"反而会带来:

• Cache Miss :每次迁移,CPU 缓存失效

• NUMA 远程访问 :中断飘到远端 NUMA 节点的 CPU,需要访问远端内存

• 软中断处理延迟:数据包在网卡队列里等待被处理的时间变得不可控

这本质上是"稳定性优先 vs 吞吐优先"的经典冲突。

systemctl status irqbalance

五、根因:一起"冤案"的真相

**根因不是 Redis,也不是应用,而是:**网络中断 & 软中断亲和性不合理

具体路径是这样的:

多队列网卡 + irqbalance 自动迁移

→ 中断分布跨 NUMA 节点

→ 软中断(NET_RX)集中 + 处理延迟

→ Pod 网络请求被"卡在内核里"

→ 应用层:Redis 请求偶发超时

六、解决方案:对症下药

设计原则:中断处理要稳定而不是"平均",IRQ / softirq / CPU / NUMA 必须协同,网络 IO 属于基础设施级负载,优先级要高。

方案一:调整网卡队列数(对齐 NUMA)

ethtool -L eth0 combined 20

目的:队列数 ≈ NUMA Node0 CPU 数,避免队列跨节点调度

方案二:增大网卡 Ring Buffer

ethtool -G eth0 rx 2048 tx 2048

目的:增强突发流量承载能力,减少 RX 丢包 / 回压

方案三:改变 irqbalance 绑核策略

1、先停掉服务

systemctl stop irqbalance

2、改用NUMA 感知的 IRQ 绑核

绑核效果 cat /etc/sysconfig/irqbalance

IRQBALANCE_BANNED_CPUS=3fffffff,ffff3fff,ffffffff

3、开启服务

systemctl start irqbalance

配置 koordinator 调度,预留核数不被业务占用

kubectl get node -o json | jq -r '

.items\[\]

| [.metadata.name,

(.metadata.annotations"node.koordinator.sh/reservation" // "")]

| @tsv

'| grep "docker042.cloud.bjmd.qihoo.net"

docker042.cloud.bjmd.qihoo.net {"resources":{"memory":"162143134516"},"reservedCPUs":"46,47,94,95"}

七、验证与方法论沉淀

效果验证维度 :

✅ Redis 访问超时消失

✅ %softirq 明显下降

✅ 中断分布稳定,不再频繁迁移

✅ Pod 网络 RT 波动显著减小

方法论沉淀 :

这不是一次"Redis 问题",而是一次系统软中断调度能力不足的问题。当你在生产环境看到以下组合时:

• 应用偶发网络超时

• Redis / MySQL 无明显瓶颈

• mtr 无稳定丢包

• CPU %soft 偏高

立刻进入 IRQ / softirq / NUMA 排查,不要在应用层和 Redis 上浪费时间。

八、尾声:经验之谈

网络延迟不一定在网络上,Redis 超时也不一定在 Redis。很多时候,问题卡在 CPU 正在"什么时候处理软中断"。

后续还有一个可以继续优化的方向:把 kubelet 和 containerd 进程也单独隔离出相应的 CPU 核数,避免它们和业务 Pod 争抢资源,进一步降低不可预期的调度抖动。

**参考文献:**https://cloud.tencent.com/developer/article/2383533

相关推荐
一条泥憨鱼几秒前
【Redis | 黑马点评】附近商铺功能源码解读
数据库·redis·缓存
念何架构之路39 分钟前
Go reflect 包:结构体反射 —Field、Tag 与 VisibleFields
java·数据库·golang
舰长11540 分钟前
将百万数据插入到 Redis,有哪些实现方案?
数据结构·redis·开源
EnCi Zheng1 小时前
PostgreSQL 实战指南:安装配置、数据类型、索引选型、MVCC 事务与高可用备份全解析
数据库·sql·postgresql·索引·1024程序员节
泡海椒2 小时前
JQuick-SQL REST API 数据接入:应用层调用接口后注册分析表
数据库·sql·1024程序员节
Random Glow2 小时前
聚簇索引 vs 二级索引:回表、覆盖索引、索引下推
数据库·mysql·性能优化·innodb·1024程序员节·索引优化
bksczm3 小时前
Redis数据结构之hash
数据结构·redis·哈希算法·1024程序员节
贵州诚鑫致达科技有限公司3 小时前
PHP两个9.2分RCE漏洞,速查版本
服务器·php·1024程序员节
要开心吖ZSH4 小时前
一次线上锁风暴复盘:号源表大范围 DELETE 的隐患与分批删除改造
数据库·mysql·行锁·1024程序员节·间隙锁·lockwaittimeout