登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis INFO commandstats 如何定位单命令 CPU 异常:calls、usec_per_call 与采样边界

来源:17golang原创

时间:2026-08-29 17:37:15 135浏览 收藏

线上 Redis 的 CPU 曲线突然抬头时,直接盯着 instantaneous_ops_per_sec 往往只能看到“忙”,看不出是哪条命令把 CPU 吃掉了。更稳妥的办法是连续采两次 INFO commandstats,用 calls 增量确认调用量,再结合 usec_per_call 和失败计数判断是调用变多、单次变重,还是请求已经在命令层被拒绝。

定位单命令 CPU 异常,不要只按累计值排序;至少比较同一窗口里的 calls 增量、usec 增量和失败计数,并把结果与业务流量变化对齐。

要点速览
  • calls 说明命令真正进入执行的次数,不能直接等同于客户端发起次数。
  • usec_per_call 是累计 CPU 微秒的平均值,必须和采样窗口、调用量一起看。
  • rejected_callsfailed_calls 能帮助区分容量拒绝和执行失败。
  • Redis 7 起部分命令统计会拆到子命令,比较历史数据时要先确认统计粒度。

先把 Redis CPU 异常拆成三个问题

同样是 CPU 上升,处理方式可能完全不同:请求量变大属于容量问题,某条命令的平均 CPU 变高更像数据规模或参数变化,failed_calls 上升则要回到调用方检查参数和数据类型。第一步不是重启 Redis,而是把“忙在哪里”固定下来。

redis-cli INFO stats
redis-cli INFO commandstats

INFO 的执行复杂度是 O(1),但返回整段统计;排查时优先请求 commandstats,减少人工阅读范围。示例中的一行可能是:

cmdstat_hget:calls=18420,usec=92100,usec_per_call=5.00,rejected_calls=0,failed_calls=2

这行只能说明从 Redis 进程启动或统计重置以来的累计情况,不能单凭 5 微秒断言当前请求一定快。

用两次快照判断调用变多还是单次变重

把第一次快照记为 A,间隔一段真实业务时间后记为 B。对同一个 cmdstat_* 项分别计算 Δcalls = B.calls - A.callsΔusec = B.usec - A.usec,窗口平均 CPU 约为 Δusec / Δcalls。如果 calls 增长很快而平均值稳定,优先看流量或重试;如果 calls 增长不大但平均值显著抬高,再查 key 大小、参数范围和数据结构。

Redis INFO commandstats 两次快照通过 calls 增量和 usec 增量区分调用变多与单次变重

实际记录时至少保留时间戳、命令名、calls、usec、usec_per_call 和业务请求量。不要把不同重启周期的累计值直接相减,也不要在采样中间执行会重置统计的操作后继续拼接窗口。

观察结果更可能的方向下一步
Δcalls 大,平均 CPU 稳定调用量、重试或流量上升对齐客户端请求数与重试计数
Δcalls 小,Δusec 明显变大单次命令成本上升核对 key 体积、成员数量和参数
failed_calls 上升命令执行失败检查数据类型、参数与调用方日志
rejected_calls 上升命令被拒绝检查资源保护、客户端限流和实例状态

把 commandstats 字段和业务症状对上

calls 是到达命令执行层的次数,usec 是该命令累计消耗的 CPU 微秒,usec_per_call 是平均值。它们回答的是 Redis 进程内部的成本,不包含客户端排队、网络往返或连接池等待。

failed_callsrejected_calls 不要混为一谈:前者表示执行过程失败,后者表示请求在执行前被拒绝。两者都为零也不代表业务正确,只能说明这两个统计项没有记录到异常。

Redis commandstats 从 calls 与 usec_per_call 到业务流量、参数规模和失败计数的排查路径

Redis 7 及之后,某些命令会按子命令分别统计。例如 ACL 相关调用可能出现带子命令的统计键。做版本升级前后的对比时,先确认 cmdstat_* 的命名粒度发生了什么变化,否则很容易把“统计拆分”误判成“调用突然减少”。

三个容易误判的采样边界

累计平均值不是当前 P99

usec_per_call 是累计平均 CPU,不是端到端延迟,也不是 P99。它适合发现趋势和做同窗口比较;长时间运行后,早期的轻请求仍会稀释最近的重请求。

空窗口不能下结论

如果两次采样之间 Δcalls 为零,就不要计算平均值,更不能用旧的累计 usec_per_call 代替本窗口结果。延长观察窗口或等待该命令再次出现即可。

统计粒度变化要单独记录

升级 Redis、切换代理或改变客户端命令组合后,命令名和子命令统计可能发生变化。排查记录中应同时保存 Redis 版本、采样命令和完整的相关 cmdstat_* 行。

从定位到修复的最小闭环

先保存两次原始输出,再做差分;接着把异常命令和业务接口、key 模式、参数范围对应起来。若是 calls 增长,先处理调用放大、重试和批量策略;若是单次成本变高,优先限制单请求处理的数据规模。修改后用同样的采样窗口复测,确认 Δusec / Δcalls 回落,同时检查失败计数没有被转移到另一条命令。

这里别急着把 usec_per_call 当成唯一告警阈值。不同命令、不同数据集的正常成本差别很大,告警更适合使用“同命令基线 + calls 增量 + CPU 总量”的组合条件。

相关问题

为什么 calls 和客户端请求数对不上?

客户端可能在连接池、代理或重试层重复发起请求,而 commandstats 统计的是到达 Redis 命令执行层的调用;还要考虑事务、脚本和子命令统计粒度。

usec_per_call 高就一定是慢查询吗?

不一定。它是 Redis 进程内的平均 CPU 消耗,不等同于完整请求延迟;网络、排队和客户端等待需要结合其他指标核对。

什么时候应该清零统计再观察?

只有在你能接受丢失累计基线、并且已保存原始快照时才考虑重置。多数线上排查优先用两次快照做差,避免影响其他审计记录。

总结

Redis INFO commandstats 最有价值的不是给出一个漂亮的排序,而是把 CPU 异常拆成可验证的差分:调用量是否增加,单次 CPU 是否变重,执行失败或拒绝是否同步上升。固定采样窗口、保留原始字段、核对版本粒度,才能让修复后的复测结果真正可比较。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>