1. 慢查询概念入门
1.1 什么是 Redis 慢查询
Redis 慢查询并非指 SQL 意义上的慢查询,而是指 命令执行耗时超过预设阈值 的操作。Redis 是单线程模型,所有命令按顺序排队执行;当某个命令处理时间过长,就会阻塞后续命令,导致整体吞吐量下降。
Redis 内部通过 slowlog-log-slower-than 和 slowlog-max-len 两个配置项来定义和记录慢查询:
| 配置项 | 默认值 | 说明 |
|---|---|---|
slowlog-log-slower-than |
10000(微秒,即 10ms) | 命令执行时间超过此值即被记录为慢查询 |
slowlog-max-len |
128 | 慢查询日志队列最大长度,超出后淘汰最旧记录 |
关键理解: 慢查询的判定单位是微秒(μs),1ms = 1000μs。默认 10ms 的阈值对于高并发场景已经偏大,生产环境通常建议调低至 1ms~5ms。
查看当前慢查询配置:
127.0.0.1:6379> CONFIG GET slowlog-log-slower-than
1) "slowlog-log-slower-than"
2) "10000"
127.0.0.1:6379> CONFIG GET slowlog-max-len
1) "slowlog-max-len"
2) "128"
查看慢查询日志:
127.0.0.1:6379> SLOWLOG GET 5
1) 1) (integer) 14 # 日志唯一ID
2) (integer) 1712345678 # Unix时间戳
3) (integer) 45678 # 执行耗时(微秒)
4) 1) "KEYS" # 命令及参数
2) "user:*"
5) "127.0.0.1:6379" # 客户端地址
6) "user-agent=redis-cli"
1.2 慢查询的危害
Redis 单线程模型决定了一个慢查询阻塞所有后续命令。其危害呈链式放大:
- 请求排队延迟: 慢查询执行期间,后续所有命令都在队列中等待,造成整体响应时间飙升。
- 连接堆积: 客户端等待超时后重试,导致 Redis 连接数暴涨,甚至触发
maxclients限制。 - 缓存雪崩风险: 慢查询集中在热点 Key 时,可能导致缓存大面积失效,请求穿透至数据库。
- 主从复制延迟: 主节点慢查询会延迟生成 RDB/AOF 或增量同步,从节点数据滞后加剧。
- 运维盲区: 未记录的慢查询会反复出现,成为性能隐患的“定时炸弹”。
真实案例: 某电商平台大促期间,一个
KEYS * 命令执行耗时 12 秒,导致 Redis 线程阻塞,上游服务超时雪崩,最终核心交易接口 502 持续 3 分钟。事后复盘发现该命令来自一个未上线的调试脚本。
1.3 为什么需要复盘慢查询
复盘慢查询不是简单的“查日志、改配置”,而是建立持续性能治理的起点:
- 定位根因: 区分是命令本身低效(如
KEYS、HGETALL大 Key)、数据量膨胀、还是网络/CPU 资源竞争。 - 量化影响: 通过慢查询频率、耗时分布、关联业务接口,评估对 SLA 的实际冲击。
- 制定优化策略: 针对不同根因采取不同手段——拆分大 Key、改用 SCAN、升级数据结构、调整阈值等。
- 建立预防机制: 将慢查询监控纳入告警体系,设置分级阈值(警告/严重),避免问题反复发生。
- 沉淀知识库: 每次复盘形成可复用的排查清单和优化模板,提升团队整体运维效率。
复盘核心公式: 慢查询复盘 = 发现(监控)→ 定位(日志+上下文)→ 分析(根因+影响)→ 优化(代码/配置/架构)→ 验证(压测+灰度)→ 沉淀(文档+告警规则)。
1.4 慢查询的判定与记录机制
Redis 慢查询日志采用固定长度环形队列存储,不会写入磁盘,重启后丢失。其工作流程如下:
- 计时起点: 命令从 socket 读取完成后开始计时,不包括排队等待时间。
- 计时终点: 命令执行完成(结果返回给客户端前)停止计时。
- 阈值比较: 执行耗时 >
slowlog-log-slower-than则入队。 - 队列淘汰: 队列满时,最旧的慢查询记录被移除。
注意: 慢查询日志只记录命令执行耗时,不包含网络传输、排队等待时间。因此实际业务感知的延迟往往比慢查询日志显示的更大。
1.5 常见慢查询命令速查
| 命令 | 时间复杂度 | 慢查询风险 | 优化建议 |
|---|---|---|---|
KEYS * |
O(N) | 极高 | 使用 SCAN 替代 |
SMEMBERS |
O(N) | 高(大 Set) | 使用 SSCAN 或拆分 Set |
HGETALL |
O(N) | 高(大 Hash) | 使用 HSCAN 或字段拆分 |
LRANGE |
O(N) | 中(大 List) | 限制返回范围,拆分 List |
ZRANGE |
O(log(N)+M) | 中(大 Zset) | 限制返回数量,使用索引 |
SORT |
O(N+M*log(M)) | 高 | 避免在大量数据上排序 |
最佳实践: 生产环境建议将
slowlog-log-slower-than 设置为 1000~3000 微秒(1~3ms),slowlog-max-len 设置为 1024 以上,确保慢查询日志能覆盖足够长的排查窗口。