【高频面试题】如何找出redis中的慢查询记录

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

从这条日志,直接拿到的信息:

  1. 什么时间:1757882300 → 转成北京时间
  2. 什么 Redis 命令:KEYS * KEYS 命令用于查找所有符合给定模式 pattern 的 keyKEYS * 就是:匹配 Redis 里所有的 key,返回全部 key 名称列表
  3. 来自哪台应用服务器:127.0.0.1

但是!默认情况下,slowlog 不会记录:接口名、方法名、调用栈、业务参数。 只靠 slowlog 本身,无法直接定位到 Java 代码 / 接口。

✅ 定位到业务代码的几种方案(面试重点)

方案 1:客户端 IP + 时间戳 + 应用日志(最常用)

  1. 取出 slowlog 的客户端 IP (应用服务器 IP)+ 时间戳
  2. 登录这台应用服务器,在应用日志里,按这个时间点检索 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。原生不提供接口、代码信息。定位方法:

  1. 通过客户端 IP 找到对应的应用服务器;
  2. 根据 slowlog 的时间戳,检索应用日志;
  3. 应用连接 Redis 设置 clientName,识别微服务;
  4. 使用 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,方便捕获慢命令。

三、面试重点坑点

  1. slowlog 是内存存储:Redis 重启后慢日志全部丢失;是环形队列,达到 max-len,老记录直接丢弃。
  2. 单位是微秒,不是毫秒! 10000 us = 10 ms,很多人踩坑。
  3. 只统计命令执行时间,不含网络 IO:客户端等待网络延迟不会计入 slowlog。
  4. 集群模式:每个节点独立 slowlog ,需要逐个节点 SLOWLOG GET,不能只查一个节点。

四、常见慢命令(面试常问)

KEYS *HGETALLLRANGE(返回大量元素)、ZRANGE、大 key 删除、SUNION 聚合类命令。

Redis 单线程,一次性大量扫描 / 返回数据就容易阻塞。

  1. KEYS pattern 全量遍历所有 key 做模式匹配,key 多的时候严重阻塞。生产禁用,用 SCAN 替代。
  2. HGETALL hash 一次性取出 hash 里面所有 field 和 value 。如果 hash 很大(上万 field),一次性读取大量数据,耗时高、占用带宽。 ✅ 替代:HSCAN 分批遍历,或者按需 HGET 取单个字段。
  3. LRANGE list LRANGE key start end。如果范围取很大(比如 LRANGE list 0 -1 取出全部元素),一次性返回海量数据,慢。 ✅ 不要一次性全拿,分页小范围读取。
  4. ZRANGE 有序集合 取出 zset 范围内大量成员。例如一次性取全部 zset 元素,数据量大就慢。 ✅ 分批,或者用 ZSCAN
  5. 大 key 删除 del 比如一个很大的 hash/list/zset,直接DEL。Redis 释放内存要一次性清理大量元素,阻塞主线程。 ✅ 先分批删除里面元素,最后再删 key;或者用 unlink(非阻塞删除,Redis4.0+)。
  6. SUNION / SINTER / SDIFF 集合聚合 求多集合的并集、交集、差集。底层要遍历多个集合全部元素计算,集合越大越慢,CPU 开销高。

五、排查步骤(口述版)

  1. 确认慢查询阈值 CONFIG GET slowlog-log-slower-than
  2. 使用 SLOWLOG GET N 获取最近慢命令;
  3. 看执行耗时、命令、客户端 IP;
  4. 分析:大 key / 全量遍历命令(KEYS、HGETALL);
  5. 优化:避免全量遍历、拆分大 key;
  6. 生产配合监控:redis-exporter + prometheus + grafana 采集慢查询指标。

面试题

题目:Redis 如何找到慢查询,slowlog 有什么特点?

参考答案

通过 SLOWLOG GET 获取慢查询记录。

slowlog 保存在内存,环形队列。

两个核心配置:

slowlog-log-slower-than 慢查询阈值(单位微秒)、

slowlog-max-len 最大日志条数。

当命令执行耗时超过阈值,就记录。

只统计命令执行时间,不包含网络 IO

Redis 重启慢日志丢失;

集群每个节点独立保存慢日志。

常见慢命令是 KEYS、HGETALL 这类全量遍历命令。

相关推荐
彧azz10 小时前
Redis 全面指南:从核心概念到高可用架构实战
数据库·redis·架构
香菜TTT12 小时前
Redis的哨兵机制
java·数据库·redis
hweiyu0014 小时前
Redis命令:APPEND
redis·缓存
敲代码的嘎仔15 小时前
从集群锁失效到异步领券:我用分布式锁 + Redisson + MQ 把领券接口 RT 从 200ms 压到 15ms
java·数据库·redis·分布式·缓存·ai·wpf
莫得感情 o20 小时前
Redis 12 · 缓存一致性:数据库与缓存双写怎么不乱
redis·缓存
吃饱了得干活21 小时前
Spring Boot + Redis 分布式锁:一个订单重复提交引发的六次迭代
java·redis·后端
草莓熊Lotso1 天前
【Redis 初阶】C++ 客户端实战:从 RESP 协议到 redis-plus-plus 工程化用法
linux·开发语言·网络·数据库·c++·redis·缓存
YHHLAI1 天前
基于 Next.js 16 + Redis 的全栈笔记博客系统
javascript·redis·笔记
码哥字节2 天前
AI一天出百本书,写不出我被Redis坑的那三天三夜
redis·ai编程工具