Redis On-CPU Profiling定位瓶颈到可视化火焰图

1 . 前置检查:确认 CPU 真的是瓶颈

在正式打性能“补丁”前,务必跑一遍系统级健康核对表(推荐 Brendan Greg 的 USE Method):

资源关注指标常用工具
CPUUtil/Idle、RunQueuetopvmstatsar
内存Fault、Swap、Cache Missfreeperf stat
I/OIOPS、Latency、Waitiostatpidstat -d
网络PPS、Rtt、Dropifstatss

当你确认 Redis 主要耗时在 CPU on-cpu,再继续以下步骤。

2 . 为可追踪重新编译 Redis

目标:既保留 -O2 优化获得真实的生产时序,又保证栈帧可解析。

# 从 Redis 源码根目录编译
make clean
make REDIS_CFLAGS="-g -fno-omit-frame-pointer"
  • -g    : 保留调试符号,便于栈回溯
  • -fno-omit-frame-pointer : 强制保留 FP 寄存器
  • -O2   : 维持 Release 优化级别

3 . 热点采样(Hotspot Analysis)

3.1 使用 perf 采样用户态 + 内核态栈

# 60 s 内以 999 Hz 频率采样 redis-server 进程
perf record -g -F 999 --pid $(pgrep redis-server) -- sleep 60
分析报告
perf report -g "graph,0.5,caller"
  • graph 展示调用关系
  • 0.5  截断阈值(≥0.5 %)
  • caller 自上而下查看“谁调用了热点函数”

3.2 使用 eBPF/BCC 的 profile 工具

内核 4.9+ 之后,BPF 方案可在内核空间折叠栈,再回写到用户态,极大降低开销。

/usr/share/bcc/tools/profile -F 999 -f \
  --pid $(pgrep redis-server) --duration 60 > redis.folded.stacks

一步到位获得 folded 格式(形如 main;call;dictFind 12),后续直接生成火焰图。


4 . 可视化:生成交互式 Flame Graph

# perf 采样
perf script > redis.perf.stacks
stackcollapse-perf.pl redis.perf.stacks > redis.folded.stacks

# 或 bcc 已直接输出 folded
flamegraph.pl redis.folded.stacks > redis.svg
  • 横轴 = 调用栈聚合后 样本占比
  • 纵轴 = 调用深度
  • 点击 SVG 方块可下钻到更深层栈帧

5 . 调用频次分析(Call Counts)

高 CPU 占用可能是 单次调用很慢,也可能是 调用极其频繁。用 BCC 的 funccount 快速把函数调用次数统计出来:

/usr/share/bcc/tools/funccount 'redis-server:(call*|*Read*|*Write*)' \
  --pid $(pgrep redis-server) --duration 60

输出示例:

FUNC                                         COUNT
call                                           334
handleClientsWithPendingWrites                 388
prepareClientToWrite                          1442

配合热点栈信息,就能判断该优化“减肥”还是“减次数”。

6 . 硬件事件采样:PMCs 诊断失速

通过 perf stat 一次性拉齐真正的 CPU IPC、Cache Miss 与 Stall 周期。

perf stat -e \
  cpu-clock,cpu-cycles,instructions, \
  uops_executed.core,uops_executed.stall_cycles, \
  cache-references,cache-misses, \
  cycle_activity.stalls_l1d_miss,cycle_activity.stalls_l2_miss, \
  cycle_activity.stalls_l3_miss \
  --pid $(pgrep redis-server) -- sleep 60

关键指标解读:

指标理想诊断思路
IPC (instructions / cycles)> 2(现代 x86)低则说明管线空转或 Cache Miss
cache-miss / cache-ref< 3 %> 10 % 多半缓存友好度差
stall_cycles / cycles越低越好高说明 CPU 在等数据

7 . 一键脚本示例

下面脚本可把 采样 + 折叠 + FlameGraph 合并执行,适合 CI / 回归测试:

#!/usr/bin/env bash
PID=$(pgrep redis-server)
DUR=60
FREQ=999
OUT=/tmp/redis_$(date +%s)

# 1) 采样
perf record -g -F $FREQ --pid $PID -- sleep $DUR

# 2) 转栈
perf script > $OUT.stacks
stackcollapse-perf.pl $OUT.stacks > $OUT.folded

# 3) 火焰图
flamegraph.pl $OUT.folded > $OUT.svg
echo "🔥 FlameGraph ready: $OUT.svg"

8 . 生产环境落地建议

  1. 采样频率999 Hz 已覆盖绝大多数业务;异常抖动场景可降到 199 Hz 减少开销。
  2. 采样窗口:确保覆盖 GC、AOF rewrite、慢查询 等高峰时段。
  3. 分段对比:升级或改代码前后做 差分 FlameGraph,一眼看出新增/消失的热点。
  4. 自动归档:用 perf-archive.sh + tar 保存 perf.data 与 Build-ID,方便异地复盘。
  5. 代码热补丁:热点定位后,可先试 serverCrondictFind 等典型函数的算法或数据结构优化,再决定是否拆分 RDB、AOF 线程。

9 . 常见疑难解答

症状排查点
FlameGraph 栈帧只有不到两层未加 -fno-omit-frame-pointer 或 strip 了 debug 符号
perf record 提示 “PERF_EVENT_OPEN failed”当前用户无 CAP_SYS_ADMIN,用 sudo 或调整 kernel.perf_event_paranoid=-1
采样时 Redis 延迟抖高频率过大 / 容器 cgroup 受限,先用 eBPF profile 或降低采样率
火焰图找不到内核函数确保安装 kernel-debuginfolinux-image-*-dbgsym

结语

  • perf + eBPF 解决“算在哪”的问题;
  • PMCs 解决“慢在哪”的问题;
  • 系统方法论 (USE / RED) 解决“该不该”的问题。

把三者串起来,就形成了 Redis CPU 优化的闭环:定位 → 可视化 → 改进 → 回归

愿你下次再看火焰图时,只为欣赏那条平稳而美丽的线!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Hello.Reader

请我喝杯咖啡吧😊

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

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

打赏作者

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

抵扣说明:

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

余额充值