慢查询日志关键在duration字段(微秒级,仅redis内部执行耗时),默认10ms阈值易漏“临界慢”,高并发场景应设为1ms(slowlog-log-slower-than 1000);其核心价值是验证优化效果,需主动监控slowlog len趋势与top命令变化。

慢查询日志不是“看看就完事”的日志,它直接暴露命令执行层的真实耗时,但SLOWLOG GET返回的每条记录里,真正关键的是duration字段——这个微秒值只包含Redis内部命令执行时间,不包含网络延迟或排队等待,所以它精准指向了你的数据结构、命令选择或Key设计问题。
怎么设置阈值才不会漏掉真实瓶颈
默认10毫秒(slowlog-log-slower-than 10000)在高并发读写场景下基本失效。比如一个MGET带50个Key,在网络正常时可能9ms完成,但它已接近单线程处理极限,再加一点负载就超时——这种“临界慢”必须捕获。
- 生产环境建议设为
1000(1毫秒),尤其对P99 RT要求 - 设为
0可记录所有命令,适合压测后做全量回溯,但会显著增加内存开销,仅限临时诊断 - 负值(如
-1)彻底关闭日志,线上禁用 -
slowlog-max-len至少设为1000,否则高频慢查询会把早期关键记录挤出队列
从SLOWLOG GET结果里快速定位真问题
别只看耗时数字。一条duration为120000微秒(120ms)的HGETALL,和一条同样耗时的KEYS *,根因完全不同:前者是大Hash膨胀,后者是全局扫描阻塞。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 先筛出高频出现的命令:
KEYS、SMEMBERS、LRANGE、SORT、HGETALL——这些基本等于“立刻改” - 检查参数长度:比如
LRANGE biglist 0 -1比LRANGE biglist 0 99耗时高几个数量级,说明是数据规模问题 - 对比同一命令不同Key的耗时:如果
HGETALL user:1001耗时2ms,而HGETALL user:9999耗时80ms,大概率是后者Value过大或字段过多 - 注意时间戳分布:若大量慢查询集中在
BGSAVE或AOF rewrite期间,说明持久化干扰了主线程,不是命令本身问题
哪些优化动作能立竿见影
很多团队花时间写监控看板,却忽略最直接有效的三件事:换命令、拆Key、压参数。
- 用
SCAN替代KEYS,用HSCAN替代HGETALL,用ZRANGEBYSCORE替代ZRANGE(当有score范围时) - 单个Hash超过1KB或字段超100个,考虑按业务维度拆成
user:1001:profile、user:1001:stats等子Key -
MGET一次取超过100个Key?先评估是否真需要全量,再确认客户端连接是否复用、Pipeline是否启用 - 复杂Lua脚本执行时间超5ms?用
SCRIPT DEBUG YES打开调试,逐行看哪一步卡住,而不是直接重写整个脚本
为什么INFO COMMANDSTATS比慢日志更值得每天扫一眼
SLOWLOG GET告诉你“哪个命令慢”,INFO COMMANDSTATS告诉你“哪个命令总耗时最高”。一个被调用1万次、平均每次0.5ms的GET,总耗时可能远超一条100ms的SORT——但后者会被记入慢日志,前者不会。
- 重点关注
cmdstat_get.instantaneous_ops_per_sec和cmdstat_get.total_calls,结合cmdstat_get.usec算出平均单次耗时 - 如果
cmdstat_set.usec突增,但SLOWLOG没记录慢SET,很可能是内存淘汰策略(如allkeys-lru)在后台频繁触发,拖慢了写入 - 配合
INFO memory里的mem_fragmentation_ratio,若>1.5且cmdstat_*整体变慢,优先执行MEMORY PURGE
慢查询日志真正的价值不在“发现慢”,而在“确认改得对不对”——每次上线优化后,盯紧SLOWLOG LEN趋势和TOP命令变化,比任何图表都直接。别让日志躺在那里,它只响应被主动读取的那一刻。










