Redis 慢查询日志保存在内存中,不是磁盘文件。
Redis 单线程,命令执行耗时超过阈值就记录。
⚠️ 耗时统计:只统计命令本身执行时间,不包含网络 IO、客户端传输等待时间Redis
一、核心命令(找出慢查询)
在 Redis 客户端redis-cli里执行。
连接上 Redis 服务之后,直接敲命令:
bash
# 连接redis
redis-cli -h 127.0.0.1 -p 6379 -a yourpassword
# 1. 获取最近N条慢查询,不写数字返回全部
SLOWLOG GET
SLOWLOG GET 10 # 获取最近10条慢日志
# 2. 查看当前慢日志总条数
SLOWLOG LEN
# 3. 清空内存里所有慢查询记录(不可恢复)
SLOWLOG RESET
一条慢日志字段含义
1) 1) (integer) 66 # 日志唯一ID
2) (integer) 1757882300 # 命令执行时间戳(Unix时间)
3) (integer) 12000 # 执行耗时,单位:微秒!12000=12ms
4) 1) "KEYS" # 命令和参数
2) "*"
5) "127.0.0.1:54321" # 客户端地址端口
6) "" # client name
从这条日志,直接拿到的信息:
- 什么时间:
1757882300→ 转成北京时间- 什么 Redis 命令:
KEYS * KEYS命令用于查找所有符合给定模式 pattern 的 key 。KEYS *就是:匹配 Redis 里所有的 key,返回全部 key 名称列表。- 来自哪台应用服务器:
127.0.0.1但是!默认情况下,slowlog 不会记录:接口名、方法名、调用栈、业务参数。 只靠 slowlog 本身,无法直接定位到 Java 代码 / 接口。
✅ 定位到业务代码的几种方案(面试重点)
方案 1:客户端 IP + 时间戳 + 应用日志(最常用)
- 取出 slowlog 的客户端 IP (应用服务器 IP)+ 时间戳
- 登录这台应用服务器,在应用日志里,按这个时间点检索 Redis 操作日志
如果项目在 Redis 操作时打印日志(记录调用接口、Redis key),就可以对上。
缺点:如果应用没有打印 Redis 调用日志,这条路走不通。
方案 2:设置 Redis client name(推荐,低成本)
应用连接 Redis 的时候,设置客户端名称。 Jedis / Lettuce 都支持:
java// lettuce示例 RedisClient client = RedisClient.create("redis://127.0.0.1:6379"); client.setClientName("order-service"); // 设置客户端名字:订单服务设置完后,
SLOWLOG GET的第 6 个字段就不再是空字符串,会显示order-service,一眼知道是哪个微服务产生的慢命令。面试加分:
CLIENT LIST命令,可以查看所有连接到 Redis 的客户端,看 client name、ip。方案 3:链路追踪(SkyWalking / Pinpoint / Jaeger,生产推荐)
项目接入 APM 链路追踪:
- 每次 Redis 操作生成一条 span,记录 Redis 命令、key、耗时、接口名、堆栈。
- 拿到 slowlog 的时间戳,去 APM 平台按时间范围 + Redis 命令检索,直接找到对应的接口和调用链路。
方案 4:Redis 监控平台(Redis Insight / 云厂商 Redis 监控)
云数据库 Redis(阿里云 / 腾讯云)自带慢查询可视化页面,部分可以关联客户端信息。
方案 5:代码埋点
在 Redis 模板封装层,统一记录 Redis 操作、耗时、调用方法名。
❗ 容易混淆的点
面试官:Redis slowlog 能看到是哪个 Java 接口发起的命令吗?
回答:
原生 slowlog 本身做不到。
slowlog 只记录 Redis 服务端收到的命令、客户端 IP、时间戳。想要定位到代码 / 接口,需要结合应用日志、clientName、APM 链路追踪。
简答版
Redis slowlog 只能拿到 Redis 命令、时间戳、客户端 IP。原生不提供接口、代码信息。定位方法:
- 通过客户端 IP 找到对应的应用服务器;
- 根据 slowlog 的时间戳,检索应用日志;
- 应用连接 Redis 设置 clientName,识别微服务;
- 使用 APM 链路追踪,直接查看 Redis 调用链路,定位接口。
追问:
KEYS *为什么是慢命令?
KEYS命令会全库遍历所有 key ,Redis 单线程,key 数量多的时候阻塞 Redis,生产禁止使用;可以用SCAN替代。
二、两个关键配置项
# 查看阈值:超过多少微秒才算慢查询
CONFIG GET slowlog-log-slower-than
# 默认值:10000 微秒 = 10ms;0=记录所有命令;负数=关闭慢日志
# 查看慢日志最多保存多少条(环形队列,满了旧记录丢弃)
CONFIG GET slowlog-max-len
# 默认:128
动态修改(临时生效,重启 Redis 丢失)
CONFIG SET slowlog-log-slower-than 5000
CONFIG SET slowlog-max-len 1000
持久化:写到 redis.conf
生产建议:
slowlog-log-slower-than=5000(5ms),slowlog-max-len=1000,方便捕获慢命令。
三、面试重点坑点
- slowlog 是内存存储:Redis 重启后慢日志全部丢失;是环形队列,达到 max-len,老记录直接丢弃。
- 单位是微秒,不是毫秒!
10000 us = 10 ms,很多人踩坑。 - 只统计命令执行时间,不含网络 IO:客户端等待网络延迟不会计入 slowlog。
- 集群模式:每个节点独立 slowlog ,需要逐个节点
SLOWLOG GET,不能只查一个节点。
四、常见慢命令(面试常问)
KEYS *、HGETALL、LRANGE(返回大量元素)、ZRANGE、大 key 删除、SUNION 聚合类命令。
Redis 单线程,一次性大量扫描 / 返回数据就容易阻塞。
- KEYS pattern 全量遍历所有 key 做模式匹配,key 多的时候严重阻塞。生产禁用,用 SCAN 替代。
- HGETALL hash 一次性取出 hash 里面所有 field 和 value 。如果 hash 很大(上万 field),一次性读取大量数据,耗时高、占用带宽。 ✅ 替代:
HSCAN分批遍历,或者按需HGET取单个字段。- LRANGE list
LRANGE key start end。如果范围取很大(比如LRANGE list 0 -1取出全部元素),一次性返回海量数据,慢。 ✅ 不要一次性全拿,分页小范围读取。- ZRANGE 有序集合 取出 zset 范围内大量成员。例如一次性取全部 zset 元素,数据量大就慢。 ✅ 分批,或者用
ZSCAN。- 大 key 删除 del 比如一个很大的 hash/list/zset,直接
DEL。Redis 释放内存要一次性清理大量元素,阻塞主线程。 ✅ 先分批删除里面元素,最后再删 key;或者用 unlink(非阻塞删除,Redis4.0+)。- SUNION / SINTER / SDIFF 集合聚合 求多集合的并集、交集、差集。底层要遍历多个集合全部元素计算,集合越大越慢,CPU 开销高。
五、排查步骤(口述版)
- 确认慢查询阈值
CONFIG GET slowlog-log-slower-than; - 使用
SLOWLOG GET N获取最近慢命令; - 看执行耗时、命令、客户端 IP;
- 分析:大 key / 全量遍历命令(KEYS、HGETALL);
- 优化:避免全量遍历、拆分大 key;
- 生产配合监控:redis-exporter + prometheus + grafana 采集慢查询指标。
面试题
题目:Redis 如何找到慢查询,slowlog 有什么特点?
参考答案
通过 SLOWLOG GET 获取慢查询记录。
slowlog 保存在内存,环形队列。
两个核心配置:
slowlog-log-slower-than 慢查询阈值(单位微秒)、
slowlog-max-len 最大日志条数。
当命令执行耗时超过阈值,就记录。
只统计命令执行时间,不包含网络 IO;
Redis 重启慢日志丢失;
集群每个节点独立保存慢日志。
常见慢命令是 KEYS、HGETALL 这类全量遍历命令。