本文是大数据系列第 44 篇,介绍 Redis 慢查询日志的工作原理与配置方法,以及一套可落地的生产性能调优策略。

完整图文版(含截图):CSDN 原文 | 掘金

慢查询日志概述

Redis 提供类似 MySQL 慢查询日志的机制,记录执行时间超过阈值的命令,帮助定位性能瓶颈。

内部实现

Redis 使用一个固定长度的 FIFO 队列存储慢查询记录:

  • 超出容量时自动淘汰最旧记录
  • 查询时间复杂度为 O(1)
  • 只记录命令执行时间,不包含网络传输和排队等待时间

配置参数

slowlog-log-slower-than

设置记录阈值,单位为微秒(1 秒 = 1,000,000 微秒)。

行为
> 0记录执行时间超过该值的命令
0记录所有命令(调试用)
< 0不记录任何命令(关闭慢日志)

默认值:10,000 微秒(10ms) 生产建议:1,000–10,000 微秒(1–10ms),根据业务 SLA 调整

# 动态修改(立即生效,重启失效)
CONFIG SET slowlog-log-slower-than 5000

# 写入配置文件(永久生效)
# slowlog-log-slower-than 5000

slowlog-max-len

设置慢日志队列最大条数。

默认值:128 生产建议:1,000–10,000(视内存允许适当调大)

CONFIG SET slowlog-max-len 1000

核心命令

# 获取最近 N 条慢查询记录(默认 10 条)
SLOWLOG GET [n]

# 查看当前慢日志条数
SLOWLOG LEN

# 清空所有慢日志
SLOWLOG RESET

SLOWLOG GET 返回格式(每条记录包含):

  1. 唯一 ID
  2. 命令执行的 Unix 时间戳
  3. 执行耗时(微秒)
  4. 命令及参数列表

性能优化策略

数据结构层

问题解决方案
Key 命名冗长使用简洁、有意义的 Key 名称
String 存大整数改用 Integer 类型(内存更小)
KEYS * 全量扫描改用 SCAN 游标迭代
HGETALL 读大 Hash改用 HMGET 指定字段或 HSCAN 分批读取
大 Value(>10KB)拆分为多个小 Key 或压缩后存储

命令层

Pipeline:将多条命令打包为一次网络请求,减少 RTT(Round-Trip Time):

// Jedis Pipeline 示例
Pipeline pipeline = jedis.pipelined();
for (int i = 0; i < 1000; i++) {
    pipeline.set("key:" + i, "value:" + i);
}
pipeline.sync();

批量命令:优先使用 MSET/MGETHMSET/HMGET 而非多次单条命令。

配置层

  • 开启 AOF 时,appendfsync everysecalways 性能更好
  • 设置 maxmemory 防止内存耗尽触发 swap,拖慢所有命令
  • 大数据集避免频繁 BGSAVE,可调大 save 触发间隔

MONITOR 命令

实时查看 Redis 接收的所有命令(含时间戳和客户端信息):

MONITOR

警告:MONITOR 会对 Redis 吞吐量产生显著影响(最高降低 50%),仅限临时调试,禁止在生产环境长期运行


监控体系建议

生产环境推荐使用以下监控栈:

Redis 实例 → redis_exporter → Prometheus → Grafana

核心监控指标

指标说明
used_memory内存使用量,接近 maxmemory 时告警
instantaneous_ops_per_sec每秒命令数,反映负载
connected_clients连接数,异常增长可能是连接泄漏
keyspace_hits/misses缓存命中率
rdb_last_bgsave_statusRDB 持久化状态
aof_current_sizeAOF 文件大小,过大时触发重写
master_link_status主从复制健康状态

测试环境快速配置

# 记录所有命令,只保留最近 2 条(用于功能测试)
CONFIG SET slowlog-log-slower-than 0
CONFIG SET slowlog-max-len 2

# 执行一些命令后查看
SET foo bar
GET foo
SLOWLOG GET

通过慢查询日志 + 监控体系的组合,可以系统性地发现并解决 Redis 性能问题,而不是依赖经验猜测。