最稳的qps监控起点是info stats中的total_commands_processed,通过多次采样差值计算并取中位数或滑动平均,结合instantaneous_ops_per_sec、keyspace_hits/misses等指标交叉分析异常原因。

用 INFO stats 抓取 total_commands_processed 是最稳的起点
Redis 本身不直接暴露“QPS”这个值,但 total_commands_processed 是累计命令数,只要做差值除以时间间隔,就是真实 QPS。它比监听 MONITOR 更轻量、比客户端埋点更客观,且不受网络抖动或客户端丢包影响。
常见错误是只采样一次就报数——比如睡 1 秒后算差值,但 Redis 命令可能集中在某几十毫秒爆发,单次采样会严重失真。正确做法是至少连续采样 3–5 次,每次间隔 1 秒,再取中位数或滑动窗口平均。
-
redis-cli info stats | grep total_commands_processed可快速验证当前值 - 脚本里别用
time.sleep(1)后立刻读,要加小偏移(如time.sleep(0.98)),避免刚好卡在秒级统计刷新边界上造成跳变 - 注意:该指标包含所有命令(
INFO、CLIENT LIST等管理命令也算),高频率运维操作会抬高基线,生产环境建议过滤掉非业务命令类型(需结合COMMANDSTATS分析)
用 Prometheus + Redis Exporter 实现趋势可视化
手动轮询 INFO 只能看瞬时值,要观察“变化趋势”,必须把数据存下来画图。Prometheus 是目前最通用的选择,而 redis_exporter 负责把 Redis 的 INFO 输出翻译成 Prometheus 能抓的指标格式。
容易踩的坑是 exporter 启动后没配对 target,或者 Redis 开了认证但 exporter 没传密码,结果 metrics 页面返回空或 401 —— 这时 curl http://localhost:9121/metrics 会直接暴露问题。
- 启动 exporter 时务必加
--redis.password=xxx(如有认证)和--redis.addr=redis://localhost:6379 - Prometheus 配置里
scrape_interval建议设为10s,太密(如1s)会给 Redis 带来额外INFO压力;太疏(如60s)会丢失波峰细节 - Grafana 中用
rate(redis_commands_total[5m])计算 QPS,别用increase()直接除时间——它对断点不鲁棒,趋势图容易突变
警惕缓存穿透/热 key 导致的 QPS 假性飙升
监控到 QPS 突增,第一反应不该是扩容,而是确认是不是异常流量。比如某个 key 失效瞬间大量请求击穿缓存,全部打到 DB 再回写 Redis,这时 Redis 的 QPS 会陡升,但实际是下游压力转移过来的假信号。
仅看 total_commands_processed 无法区分正常业务增长和异常穿透,必须联动其他指标交叉判断:
- 查
redis-cli --stat或INFO stats中的instantaneous_ops_per_sec,它反映实时指令速率,若远高于rate(total_commands_processed),说明有短时脉冲 - 对比
keyspace_hits和keyspace_misses,命中率骤降到85%以下大概率是穿透或 key 批量失效 - 用
redis-cli --hotkeys(Redis 4.0+)或SLOWLOG GET 10查是否有单个命令耗时 >50ms,热 key 读通常伴随高延迟
Python 脚本实现带缓冲的 QPS 采集(附防抖逻辑)
不是所有环境都能上 Prometheus,有时一个轻量脚本就能满足短期趋势分析需求。关键是要加环形缓冲区,避免把每秒原始值全记下来撑爆内存,同时支持滚动计算最近 N 秒的平滑值。
下面这段代码跑起来后,每秒输出的是过去 5 秒的加权平均 QPS,比单点值抗噪能力强得多:
import redis
import time
from collections import deque
<p>client = redis.StrictRedis(host="localhost", port=6379, decode_responses=True)
window = deque(maxlen=5) # 存最近5次的 commands_processed 值</p><p>while True:
try:
curr = int(client.info("stats")["total_commands_processed"])
window.append(curr)
if len(window) >= 2:
qps = (window[-1] - window[0]) / (len(window) - 1)
print(f"QPS_5s_avg: {qps:.1f}")
except Exception as e:
print(f"err: {e}")
time.sleep(1)</p>
注意:别用 time.time() 做时间戳对齐,sleep 不精确;也别把 window 设太大(比如 60),否则冷启动后前几十秒数据全是 0,趋势图开头会塌陷。
真正难的从来不是“怎么画出一条线”,而是当这条线突然翘起时,你手边有没有 keyspace_misses、used_memory_peak_human、latest_fork_usec 这几个指标一起看——它们不说话,但合起来能告诉你,到底是用户变多了,还是 Redis 自己快扛不住了。










