【Redis从入门到精通】第61篇:慢查询日志——找出Redis性能瓶颈的利器
2026/6/5 22:42:33 网站建设 项目流程

上一篇【第60篇】二进制位数组——Redis的BitMap有多好用
下一篇【第62篇】# Redis监视器——MONITOR命令的原理与实战


程序员A:“线上Redis突然变慢了,怎么办?”
程序员B:“慌什么,查慢查询日志啊。”
程序员A:“慢查询日志是啥?”
程序员B:“……你被优化了。”

在Redis的使用过程中,性能问题是最让人头疼的。你可能会遇到响应时间突然飙升、QPS下降、甚至超时报警等情况。面对这些问题,盲人摸象式地排查是行不通的,你需要一个"记录仪"来帮你找出罪魁祸首——这就是Redis的慢查询日志(Slow Log)

一、什么是慢查询日志

慢查询日志,顾名思义,就是记录那些"跑得慢"的命令。当一个命令的执行时间超过你设定的阈值时,Redis就会把这个命令记录下来。

这里有一个关键点要强调:慢查询日志记录的是命令执行时间,而不是整个请求的网络往返时间。也就是说,从客户端发送命令到Redis收到命令这段时间是不算在内的,只有Redis真正开始执行到执行完毕的时间才会被记录。

客户端 Redis服务器 | | |--- 发送 KEYS * 命令 ----------------->| 网络传输时间(不计入) | | 排队等待时间(不计入) | | ======== 执行计时开始 ======== | | 遍历所有Key... (500万条记录) | | ======== 执行计时结束 ======== |<-- 返回 500万个Key --------------------| | | 总耗时:3000ms | 执行耗时:2900ms(被记录为慢查询)

所以,如果你的慢查询日志里空空如也,但客户端还是觉得慢,那问题可能出在网络延迟、客户端处理逻辑、或者Redis在排队(被其他慢命令阻塞)。

二、慢查询日志的两个核心配置

Redis提供了两个配置项来控制慢查询日志的行为:

2.1 slowlog-log-slower-than:执行时间阈值

这个配置项设定了"多慢才算慢"的门槛,单位是微秒(microsecond),1秒 = 1,000,000微秒。

# redis.conf 配置 slowlog-log-slower-than 10000 # 默认值:10000微秒 = 10毫秒

几个典型值:

配置值含义
10000(默认)执行时间超过10ms才记录
0记录所有命令(调试时用,生产慎用)
-1关闭慢查询日志(不推荐)
1000执行时间超过1ms才记录(较严格)
500000执行时间超过500ms才记录(较宽松)

生产环境建议设置为1000(1ms)左右,这样能捕获大部分有问题的命令,同时不会产生太多噪音。

2.2 slowlog-max-len:日志最大条数

Redis的慢查询日志保存在内存中(一个固定长度的队列),所以需要限制最大条数。

# redis.conf 配置 slowlog-max-len 128 # 默认值:最多保留128条

工作原理:当慢查询日志条数达到上限时,Redis会采用**FIFO(先进先出)**策略,淘汰最早的那条记录。这意味着如果你设置得太小,新产生的慢查询可能会把旧的挤掉,导致你来不及分析。

内存中的慢查询日志队列: 慢查询日志(固定长度队列) ┌──────────────────────────────────────────────────┐ │ [最新] id:156 SLOWLOG GET 2.3ms │ │ id:155 KEYS * 150ms │ │ id:154 LRANGE bigkey 0 -1 80ms │ │ id:153 HGETALL big-hash 45ms │ │ ... │ │ [最早] id:29 FLUSHALL 3ms │ └──────────────────────────────────────────────────┘ ↑ 新记录从头部插入,满了就从尾部删除最旧的

生产环境建议设置为500或更高,确保有足够的历史记录用于分析。

2.3 动态修改配置

好消息是,这两个参数都支持运行时动态修改,无需重启Redis:

# 修改慢查询阈值为1ms127.0.0.1:6379>CONFIG SET slowlog-log-slower-than1000OK# 修改日志最大条数为500127.0.0.1:6379>CONFIG SET slowlog-max-len500OK# 查看当前配置127.0.0.1:6379>CONFIG GET slowlog-log-slower-than1)"slowlog-log-slower-than"2)"1000"

当然,记得把配置也写到redis.conf里,否则重启后就失效了。

三、慢查询日志的存储结构

慢查询日志存储在Redis服务器的内存中,不写入磁盘。这意味着:

  1. Redis重启后,慢查询日志会清空
  2. 慢查询日志本身几乎不占额外磁盘空间
  3. 查询慢查询日志非常快,零I/O开销

每条慢查询日志记录包含4个字段

┌─────────────────────────────────────────────────────────────┐ │ 一条 Slowlog 记录的结构 │ ├──────────────┬──────────────────────────────────────────────┤ │ 字段 │ 说明 │ ├──────────────┼──────────────────────────────────────────────┤ │ id │ 日志的唯一标识ID,自增,从1开始 │ ├──────────────┼──────────────────────────────────────────────┤ │ timestamp │ 命令执行时的UNIX时间戳(秒级) │ ├──────────────┼──────────────────────────────────────────────┤ │ duration │ 命令执行耗时,单位:微秒 │ ├──────────────┼──────────────────────────────────────────────┤ │ args │ 命令及其参数,以数组形式保存 │ └──────────────┴──────────────────────────────────────────────┘

实际输出示例:

127.0.0.1:6379>SLOWLOG GET11)1)(integer)156# 日志ID2)(integer)1716278400# 时间戳3)(integer)2300# 执行耗时:2300微秒 = 2.3毫秒4)1)"LRANGE"# 命令2)"user:messages:10086"# 参数13)"0"# 参数24)"-1"# 参数3

注意一个细节:Redis会对命令参数进行脱敏处理。比如运行AUTH password命令时,密码会被替换成******,防止敏感信息泄露在日志中。

四、慢查询日志的三大操作命令

4.1 SLOWLOG GET:获取慢查询日志

# 获取所有慢查询日志(最多显示slowlog-max-len条)127.0.0.1:6379>SLOWLOG GET# 获取最近10条127.0.0.1:6379>SLOWLOG GET10

输出格式是嵌套数组,不太方便阅读。实际使用中,建议配合脚本或工具进行格式化展示。

4.2 SLOWLOG LEN:查看日志数量

127.0.0.1:6379>SLOWLOG LEN(integer)42

这个命令适合用来做监控告警——当慢查询日志数量快速增长时,说明系统可能出了问题。

4.3 SLOWLOG RESET:清空慢查询日志

127.0.0.1:6379>SLOWLOG RESET OK

踩坑提示:SLOWLOG RESET 会清空所有慢查询日志,操作前请确保你已经分析完或导出了需要的数据。建议在执行前先用 SLOWLOG GET 导出备份。

五、生产实践:慢查询分析流程

知道了命令怎么用,关键是怎么在实际生产中运用。这里给你一套系统的慢查询分析流程:

┌─────────────────────────────────────────────────────────────────┐ │ 慢查询分析流程 │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ 1.设置 │───>│ 2.定期 │───>│ 3.统计 │───>│ 4.针对性 │ │ │ │ 合理阈值 │ │ 采集日志 │ │ 分析归因 │ │ 优化解决 │ │ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ │ │ ┌──────────┐ │ │ │ └─────────────>│ 5.持续 │<─────────────────────┘ │ │ │ 监控验证 │ │ │ └──────────┘ │ └─────────────────────────────────────────────────────────────────┘

5.1 设置合理的阈值

# 步骤1:设置1ms阈值,捕获更多信息CONFIG SET slowlog-log-slower-than1000CONFIG SET slowlog-max-len1000

5.2 定期采集和分析

写一个简单的脚本,定期采集慢查询日志,统计分析:

# slowlog_analyzer.py - 简单的慢查询分析脚本importredisfromcollectionsimportCounter r=redis.Redis(host='localhost',port=6379)slowlogs=r.slowlog_get(200)# 获取最近200条# 统计各命令的慢查询次数cmd_counter=Counter()forloginslowlogs:cmd=log['command'].split()[0]# 取命令名cmd_counter[cmd]+=1# 输出Top 10慢查询命令print("=== Top 10 慢查询命令 ===")forcmd,countincmd_counter.most_common(10):print(f"{cmd}:{count}次")# 找出执行时间最长的10条sorted_logs=sorted(slowlogs,key=lambdax:x['duration'],reverse=True)print("\n=== 执行时间最长的10条 ===")forloginsorted_logs[:10]:duration_ms=log['duration']/1000print(f" [{duration_ms:.2f}ms]{log['command'][:80]}")

5.3 常见慢查询命令及优化建议

这是实战中最有价值的部分——遇到慢查询了,怎么优化?

慢查询命令慢的原因优化方案
KEYS *O(N) 全量扫描所有KeySCAN替代,增量式遍历
LRANGE key 0 -1一次性取出整个ListLLEN判断长度 + 分批LRANGE
HGETALL key大Hash取出所有字段HSCAN增量获取 或只取需要的字段
SMEMBERS key大Set取出所有成员SSCAN增量获取
ZRANGE key 0 -1大ZSet取出所有成员ZSCAN或限定范围
FLUSHALL清空整个数据库UNLINKDEL删除特定Key
SORT key对大数据量排序预计算/在业务层排序/限制排序范围
SUNION多个大Set多个大Set取并集拆分操作/控制Set大小

踩坑提示KEYS *是慢查询排行榜的"常客"。生产环境严禁使用KEYS,改用SCAN命令。SCAN是游标式的迭代器,不会阻塞Redis。

SCAN 替代 KEYS 的示例:

# 危险!生产环境不要用KEYS user:*# 安全!用SCAN替代SCAN0MATCH user:* COUNT100# 返回: 1) "12345" (下次迭代用的游标)# 2) 1) "user:1001"# 2) "user:1002"# ...

六、搭配 INFO commandstats 深入分析

慢查询日志能帮你找到"最慢的命令",但它有一个局限:只记录超过阈值的命令。有些命令执行不算慢(比如每次0.5ms),但调用极其频繁(每秒10000次),累积起来的影响也是巨大的。

这时候,INFO commandstats就派上用场了:

127.0.0.1:6379>INFO commandstats# Commandstatscmdstat_get:calls=15234567,usec=7654321,usec_per_call=0.50cmdstat_set:calls=8923456,usec=3456789,usec_per_call=0.39cmdstat_lrange:calls=345678,usec=2345678,usec_per_call=6.79cmdstat_hgetall:calls=56789,usec=1234567,usec_per_call=21.74

每个命令的统计信息包含三个关键字段:

  • calls:调用次数
  • usec:总耗时(微秒)
  • usec_per_call:平均每次调用耗时

通过INFO commandstats你可以发现一些慢查询日志遗漏的问题:

  • 高频低延迟命令:单次快但总量大,如GET/SET
  • 低频高延迟命令:频率不高但单次很慢,如HGETALL
# 提取有用的统计信息127.0.0.1:6379>INFO commandstats|grep-E"cmdstat_|usec_per_call"cmdstat_get:calls=15234567,usec=7654321,usec_per_call=0.50cmdstat_hgetall:calls=56789,usec=1234567,usec_per_call=21.74# 平均21.74ms!需优化

七、慢查询与 LATENCY HISTORY 的配合

除了慢查询日志和INFO commandstats,Redis还提供了LATENCY系列命令来监控延迟:

# 查看最近的延迟事件127.0.0.1:6379>LATENCY LATEST# 查看延迟的历史统计(每秒采样一次)127.0.0.1:6379>LATENCY HISTORYcommand1)1)(integer)17162783002)(integer)5002)1)(integer)17162783012)(integer)12003)1)(integer)17162783022)(integer)300# 查看延迟图表(终端输出ASCII柱状图)127.0.0.1:6379>LATENCY DOCTOR

LATENCY DOCTOR会给出一份诊断报告,自动分析延迟原因并给出建议,就像Redis自带的"老中医"。

三者配合使用的最佳实践:

┌──────────────────────┐ │ 慢查询日志 (SLOWLOG) │─── 找出"最慢的单次命令" └──────────────────────┘ ┌──────────────────────┐ │ INFO commandstats │─── 发现"高频但累积慢"的命令 └──────────────────────┘ ┌──────────────────────┐ │ LATENCY 系列 │─── 监控整体延迟趋势和异常 └──────────────────────┘ 三者配合 → 全面掌握Redis性能状况

小结

慢查询日志是Redis性能调优的"第一站"。通过合理配置slowlog-log-slower-thanslowlog-max-len,结合SLOWLOG GET/LEN/RESET三大命令,再搭配INFO commandstatsLATENCY系列,你就能构建一套完整的Redis性能监控体系。

记住几个关键点:

  1. 阈值建议设为1000(1ms),日志条数建议500+
  2. 慢查询日志存在内存中,重启会丢失
  3. 不在慢查询日志里不代表没问题,还要看INFO commandstats
  4. 遇到KEYS *LRANGE 0 -1HGETALL要果断优化

上一篇【第60篇】二进制位数组——Redis的BitMap有多好用
下一篇【第62篇】# Redis监视器——MONITOR命令的原理与实战


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询