Redis作为高性能内存数据库,在高并发场景下偶尔会出现命令执行时间异常拉长的情况。要弄清到底是哪条命令在消耗时间,并不需要借助外部监控系统的复杂埋点,Redis自身提供的慢查询机制已经足够实用。慢查询日志会把执行耗时超过设定阈值的命令自动记录下来,而读取这些记录最核心的操作就是SLOWLOG GET。掌握它的使用方式和输出结构,是每一位后端开发者排查Redis性能问题的基础能力。

慢查询日志的工作原理与配置项解析
Redis的慢查询日志并非记录所有命令,而是基于一个时间阈值进行过滤。这个阈值由配置项slowlog-log-slower-than控制,单位是微秒。默认情况下该值为10000,也就是10毫秒。只有执行时间严格大于这个值的命令才会被写入慢查询日志队列。需要注意的是,这里统计的是命令真正在Redis服务端执行所消耗的时间,不包括网络传输和客户端排队等待的时间,因此它反映的是Redis自身处理命令的繁忙程度。
另一个关键配置是slowlog-max-len,它决定了慢查询日志最多保留多少条记录。由于Redis使用了一个先进先出的队列来存放这些日志,当记录数量达到上限后,最旧的日志会被新日志覆盖。默认值为128,在生产环境中如果流量较大,建议适当调高到1000左右,避免重要线索被快速冲掉。这两个配置既可以通过redis.conf文件静态设置,也可以在运行时用CONFIG SET动态修改,动态修改后无需重启实例即可生效。
从底层实现来看,Redis在每次执行命令的前后都会记录微妙级时间戳,计算差值后判断是否超过阈值。整个过程对正常命令路径的侵入极小,仅多了一次时间获取和比较操作。也正因如此,开启慢查询日志几乎不会带来可感知的性能损耗,反而能在出问题后提供极具价值的现场证据。理解这套机制,我们就能明白为什么SLOWLOG GET拿到的数据既轻量又精准。
SLOWLOG GET命令的详细用法与输出解读
获取慢查询日志最直接的方式就是在Redis客户端中执行SLOWLOG GET。该命令支持一个可选的数字参数,用来指定最多返回多少条记录。如果不传参数,则返回当前队列中的全部日志。例如SLOWLOG GET 10表示只拿最近的10条。返回的每一条日志都是一个数组,按照固定顺序包含四个元素:日志唯一ID、命令执行时的Unix时间戳、耗时微秒数,以及命令本身及其参数列表。部分较新版本的Redis还会附带客户端IP端口和客户端名称等字段。
下面是一段在redis-cli中执行并获取结果后格式化展示的示例。通过这段代码可以直观看到输出结构:
# 连接redis并执行
redis-cli
127.0.0.1:6379> SLOWLOG GET 2
1) 1) (integer) 14
2) (integer) 1715839102
3) (integer) 21000
4) 1) "KEYS"
2) "user:*"
5) "127.0.0.1:52134"
6) ""
2) 1) (integer) 13
2) (integer) 1715839080
3) (integer) 15300
4) 1) "HGETALL"
2) "big_hash:session:9912"
在上述输出中,第一条日志ID为14,发生在时间戳1715839102,耗时21000微秒即21毫秒,执行的是KEYS user:*。这显然是一个危险操作,因为在生产环境用KEYS做全量模糊匹配会遍历整个键空间。第二条是一个对大哈希对象的HGETALL,同样耗时偏高。通过这种结构化的返回,我们可以快速按耗时排序,优先处理最慢的命令。
除了直接查看,还可以配合SLOWLOG LEN获取当前日志条数,或用SLOWLOG RESET清空日志。在排查某个时间段的问题时,先RESET再观察一段时间后的GET结果,能排除历史噪声。这种组合操作在实战中非常常见,也比盲目翻查监控图表更高效。
基于慢查询日志定位并优化性能瓶颈
拿到SLOWLOG GET的输出后,下一步就是归类分析。最常见的几类慢命令包括:KEYS模糊遍历、大对象的HGETALL或SMEMBERS、复杂度高的SORT、以及一次性写入巨量元素的MSET或LPUSH。对于KEYS类问题,应改为使用SCAN命令增量迭代,避免阻塞主线程。对于大哈希,可以考虑将字段拆分到多个小key,或者只取需要的字段用HMGET。
我们也可以用一段简单的Python脚本定时拉取慢日志并做聚合统计,从而发现重复出现的坏命令模式:
import redis
client = redis.StrictRedis(host='127.0.0.1', port=6379, decode_responses=True)
logs = client.slowlog_get(100)
cmd_count = {}
for log in logs:
# log['command']是完整命令字符串
cmd = log['command'].split()[0]
cmd_count[cmd] = cmd_count.get(cmd, 0) + 1
for cmd, cnt in sorted(cmd_count.items(), key=lambda x: -x[1]):
print(f"命令 {cmd} 出现 {cnt} 次")
上述脚本把最近100条慢日志按命令类型计数,帮助团队识别是某类操作普遍慢,还是个别key异常。如果发现HGETALL频繁上榜,就要检查是否存在未控制大小的哈希结构。此时结合MEMORY USAGE命令查看具体key的内存占用,便能形成完整的优化证据链。
从架构层面看,慢查询日志还能反映实例是否处于CPU饱和状态。如果大量不同命令都出现偶发慢日志,且耗时集中在同一时间段,往往说明机器资源争抢或持久化fork阻塞。此时单靠优化命令不够,可能需要升级实例规格、拆分热点key,或调整save策略。把SLOWLOG GET作为日常巡检的一环,能够让性能治理从救火转向预防。
RedisSLOWLOG_GETslow_query_log修改时间:2026-08-18 02:48:14