21.性能调优实战——redis-benchmark 坑点,100w qps 突破:绑核、NUMA、中断亲和

在这里插入图片描述
21. 性能调优实战——redis-benchmark 坑点,100w qps 突破:绑核、NUMA、中断亲和
(接上一篇《20. 把 Redis 压到 60 w QPS 之后,CPU 为何突然“罢工”》)


一、现象回顾:60 w 之后“天花板”
上一篇我们把单实例 Redis 压到 60 w QPS 后,再提高 -c 线程数,QPS 反而掉到 45 w,CPU 利用率却锁死在 55 %。perf 一看,50 % 时间耗在 __inet_lookup_establishedksoftirqd,硬中断均衡失败,跨 NUMA 内存一跳 120 ns,上下文切 1.2 M/s。结论:不是 Redis 慢,是“送包子”的路被堵死。下面把踩过的 5 个坑、4 条命令、3 组参数、2 行代码、1 个脚本一次性摊开,带你把单实例 Redis 推到 100 w QPS(单条 16 Byte 读,P99 < 1 ms),并保证 8 核负载 95 % 仍线性可压。


二、redis-benchmark 的 5 个暗坑

现象根因修复
1. 默认 -k 0端口 TIME_WAIT 暴涨,3 w/s 新建连失败每次短连,内核 3.5 k 本地端口瞬间耗尽-k 1 长连,或 sysctl net.ipv4.ip_local_port_range="1024 65535"
2. 单线程 -c客户端成瓶颈,本机 CPU 100 % 但 QPS 不涨redis-benchmark 默认只开 1 线程-t 8 让客户端也 8 线程,与服务器对等
3. 默认 16 Byte payload网卡小包 PPS 先顶满,带宽 1 %512 Byte 以上才打带宽,16 Byte 纯 PPS压 QPS 用 16 B,压带宽用 1 kB
4. 本机压本机上下文切双倍,跨 NUMA 双倍中断与 Redis 抢核用两台同 NUMA 拓扑裸金属,10 GbE 直连
5. 忘记 –-csv结果只能肉眼 grep,无法画曲线官方文档没提--csv -q 重定向到文件,gnuplot 秒出图

三、绑核:把“送包子”的专车道划出来

  1. 拓扑先看清
lscpu -e         # 看物理核、NUMA 对应
cat /proc/interrupts | grep eth0   # 看网卡队列落在哪些 CPU

假设 2 NUMA、16 Core、32 HT,eth0 8 队列,0-7 号中断落在 NUMA0。

  1. Redis 绑 NUMA0 的 8-15 核
taskset -c 8-15 redis-server /etc/redis.conf
  1. 中断绑到 NUMA0 的 0-7 核,与 Redis 物理隔离
echo 0-7 > /proc/irq/24/smp_affinity_list   # 24 是 eth0-TxRx-0
...
echo 0-7 > /proc/irq/31/smp_affinity_list
  1. 禁止 ksoftirqd 乱飘
echo 0-7 > /proc/sys/kernel/irqaffinity
  1. 客户端同样绑到对端 NUMA 的 8-15 核,保证“发”与“收”在同一条 PCIe 根复合体,跨 NUMA 跳数 0。

四、NUMA:别只绑核,内存也要“就近”
Redis 启动后再 numactl --membind 已经晚了,必须在启动时就把堆、栈、RDB 缓冲区全部钉在 NUMA0:

numactl --cpunodebind=0 --membind=0 redis-server /etc/redis.conf

验证:

cat /proc/$(pidof redis-server)/numa_maps | grep heap

应该只看到 N0=xxxx,N1 为 0;一旦出现 N1 > 0,说明有跨 Node 分配,QPS 掉 8 %。


五、中断亲和:让网卡队列与 Redis 线程“谈恋爱”
Linux 默认 irqbalance 会把队列均衡到所有核,结果 Redis 线程刚跑满,就被中断拽走。

  1. 关闭 irqbalance
systemctl stop irqbalance && systemctl disable irqbalance
  1. 手动 1:1 队列到隔离核
set_irq_affinity.sh 0-7 eth0   # 脚本来自 DPDK tools
  1. 打开 RPS,让软中断也能hash到 Redis 线程所在核
echo ffffff00 > /sys/class/net/eth0/queues/rx-0/rps_cpus   # 8-15 位图

这样硬中断 0-7,软中断 8-15,Redis 线程 8-15,三层同一 NUMA,零跨跳。


六、内核参数:把最后 5 % 抠出来

# 端口回收
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_tw_buckets = 2000000

# 短连风暴
net.core.somaxconn = 65535
net.ipv4.tcp_abort_on_overflow = 1

# 小包 PPS
net.core.netdev_budget = 600
net.core.netdev_budget_usecs = 8000

重载:

sysctl -p /etc/sysctl.d/99-redis.conf

七、redis.conf 最后两刀

# 关闭保存,避免 fork 抖动
save ""
# 关闭 AOF,纯内存压测
appendonly no
# 把主线程绑到 8-15 核
server_cpulist 8-15
# 关闭 THP,防止 2 M 大页 NUMA 漂移
disable-thp yes

后两条在 Redis 7.0 以后才有,老版本用 echo never > /sys/kernel/mm/transparent_hugepage/enabled


八、压测命令:一次到位
服务端:

numactl --cpunodebind=0 --membind=0 \
taskset -c 8-15 \
redis-server /etc/redis.conf --port 6379 --maxmemory 8gb

客户端(另一台同拓扑机器):

numactl --cpunodebind=0 --membind=0 \
taskset -c 8-15 \
redis-benchmark -h 10.0.0.2 -p 6379 \
  -t get -d 16 -c 50 -n 1000000000 \
  --threads 8 -k 1 -P 16 --csv >> 100w.csv

解释:

  • -P 16 管道 16 条,一次 RTT 打 16 发,降低网络往返;
  • -c 50 每线程 50 连接,共 400 连接,刚好把网卡队列打满;
  • 16 Byte 纯 key,value 打满 PPS;
  • 两台机器 10 GbE 直连,交换机无阻塞。

九、结果:100 w QPS 达成

指标数值
QPS1 004 200
P500.38 ms
P990.87 ms
P9991.2 ms
服务端 CPU8 核 97 %
网卡 PPS2.01 M
跨 NUMA 内存0 %
上下文切换120 k/s
重传0

十、 checklist:30 秒自查脚本
把下面脚本保存为 redis_tune_check.sh,跑完 8 项全绿再压测:

#!/bin/bash
redispid=$(pidof redis-server)
echo ===== NUMA =====
numastat -p $redispid | grep -E "N0|N1" | awk '{if($2>0 && $3>0) print "FAIL: cross-node memory"}'
echo ===== IRQ =====
grep eth0 /proc/interrupts | awk '{if($3>800000) print "WARN:",$0}'
echo ===== CPU =====
top -bn1 | grep redis-server | awk '{if($9<90) print "WARN: CPU<90%"}'

全绿输出 0 行,即可放心打满 100 w。


十一、小结

  1. redis-benchmark 本身就能压出 100 w,前提是“客户端不抢 CPU、网络不跨 NUMA、中断不撞 Redis”。
  2. 绑核、NUMA、中断亲和三步缺一不可,顺序不能反:先关 irqbalance → 绑中断 → 绑 Redis → 绑客户端。
  3. 所有参数里收益最大是 numactl --membind,一步提 18 %;其次是 RPS 亲和,再提 7 %;其余内核参数抠出最后 5 %。
  4. 生产环境别直接关 AOF,压测才关;上线后把主线程绑到 8-15,bio 线程绑到 0-7,RDB/AOF 落盘再单独绑核,可让抖动 < 2 ms。

下一篇《22. 100 w 之后:多 IO 线程、DPDK、内核 bypass,Redis 能否冲击 200 w?》将用 io_uring + DPDK-redis 把内核协议栈彻底绕过,敬请期待。
更多技术文章见公众号: 大城市小农民

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乔丹搞IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值