慢查询本质是某类命令在特定条件下持续变慢,需从执行时间、参数规模、资源状态三层分析:先查slowlog len和INFO stats判断是否高频阻塞,再结合slowlog-log-slower-than阈值、命令模式、大键热键验证及配置干扰综合定位。

慢查询不是“某条命令慢”,而是“某类命令在某种条件下持续变慢”——直接看 slowlog get 只能看到表象,真正要解决,得顺着执行时间、参数规模、资源状态三层往下挖。
怎么快速确认是不是慢查询真凶?
别一上来就翻日志。先做两件事:
- 执行
slowlog len看当前积压多少条,如果长期 > 500(且slowlog-max-len设的是 1000),说明慢命令高频发生,不是偶发 - 对比
INFO stats中的total_commands_processed和instantaneous_ops_per_sec:如果 OPS 暴跌但连接数/请求量没降,大概率是主线程被阻塞,而非客户端问题 - 注意
slowlog-log-slower-than的实际值——很多线上环境仍用默认 10000(10ms),但业务 SLA 要求 2ms,这时slowlog get根本看不到真实瓶颈
从 slowlog 输出里一眼识别高危模式
slowlog get 返回的每条记录里,真正要盯的是第三项(执行时间)和第四项(命令+参数)。常见危险信号:
- 时间戳相近的多条记录都含
KEYS、FLUSHDB、DEBUG类命令 → 运维误操作或脚本失控 - 同一键名反复出现在
HGETALL、SMEMBERS、LRANGE中,且第三项时间 > 50000(50ms)→ 极可能是大键(bigkey),立刻用MEMORY USAGE key_name验证 - 大量
SET或DEL出现在慢日志里 → 不是命令本身慢,而是内存分配/释放耗时,指向内存碎片率高(INFO memory查mem_fragmentation_ratio> 1.5 就危险)
大键和热键必须现场验证,不能只靠日志猜
日志里看到 HGETALL large_user_profile 执行了 80ms,不代表就是它的问题——可能只是刚好撞上 fork 或 AOF rewrite。验证步骤要闭环:
- 用
redis-cli --bigkeys扫描,但注意:它会遍历所有键,生产环境慎用;更安全的是对疑似键单独跑MEMORY USAGE large_user_profile+TYPE large_user_profile - 热键判断不能只看访问频次,要结合
INFO commandstats:比如cmdstat_get:calls=123456,usec=890123,usec_per_call=7.2,平均 7.2μs 正常,但如果某次GET单独花了 50ms,说明有排队或锁竞争 - 确认是热键后,别急着加本地缓存——先查客户端是否用了连接池,
redis-cli --latency看网络延迟,再查 Redis 实例 CPU 是否飙到 90%+(top -p $(pgrep redis))
配置和持久化干扰经常被忽略
很多团队优化完命令和数据结构,慢查询还是偶发,问题往往藏在后台:
- AOF 的
appendfsync everysec在磁盘写满或 IO 延迟高时,会导致每秒一次的主线程阻塞,表现为周期性慢查询(集中在整秒时刻);改用no前先确认业务能否接受宕机丢数据 -
bgrewriteaof或bgsave触发时,fork 子进程会复制页表,若 Redis 内存 > 10GB,fork 耗时可能达百毫秒——查INFO persistence的latest_fork_usec,超 100000(100ms)就得调优 -
maxmemory接近阈值时,淘汰策略(如volatile-lru)会触发额外扫描,加剧延迟;监控evicted_keys指标,持续增长说明内存真的不够用
真正难处理的从来不是单个慢命令,而是多个小问题叠加:一个中等大小的 Hash 键 + AOF everysec + 磁盘 IO 波动 + 客户端连接池过小,四者同时发生才让 P99 延迟破表。定位时别跳步,从 slowlog 到 INFO 到系统指标,一层层剥开。


















