Skip to content

Redis 慢查询分析

慢查询日志配置

慢查询阈值设置

Redis 慢查询日志记录执行时间超过阈值的命令,默认阈值为 10000 微秒(10 毫秒)。可以通过以下配置调整阈值:

bash
# 临时设置,重启后失效
redis-cli config set slowlog-log-slower-than 5000

# 永久设置,修改 redis.conf 文件
slowlog-log-slower-than 5000

慢查询日志长度

Redis 慢查询日志存储在内存中,默认最多保存 128 条记录。可以通过以下配置调整日志长度:

bash
# 临时设置,重启后失效
redis-cli config set slowlog-max-len 1000

# 永久设置,修改 redis.conf 文件
slowlog-max-len 1000

慢查询日志持久化

Redis 慢查询日志默认只保存在内存中,重启后会丢失。可以通过以下方式实现持久化:

bash
# 定期将慢查询日志导出到文件
redis-cli slowlog get > /var/log/redis/slowlog_$(date +%Y%m%d_%H%M%S).log

# 使用 Redis 客户端库编写脚本,定期导出慢查询日志

慢查询日志查看

使用 redis-cli 查看

bash
# 查看所有慢查询日志
redis-cli slowlog get

# 查看最近 10 条慢查询日志
redis-cli slowlog get 10

# 查看慢查询日志统计信息
redis-cli slowlog len
redis-cli slowlog reset

慢查询日志格式

慢查询日志包含以下字段:

  • 日志 ID:自增唯一标识符
  • 时间戳:命令执行时间
  • 执行时间:命令执行耗时(微秒)
  • 命令及参数:执行的 Redis 命令和参数

示例输出:

1) 1) (integer) 100
   2) (integer) 1620000000
   3) (integer) 5000
   4) 1) "KEYS"
      2) "user:*"

慢查询分析方法

常见慢查询类型

  1. 全键扫描命令

    • KEYS pattern
    • FLUSHDB
    • FLUSHALL
  2. 大键操作

    • HGETALL large_hash
    • LRANGE large_list 0 -1
    • SMEMBERS large_set
  3. 复杂计算命令

    • SORT large_list
    • BGREWRITEAOF
    • BGSAVE
  4. 事务和 Lua 脚本

    • 长时间运行的 MULTI/EXEC 事务
    • 复杂的 Lua 脚本

慢查询分析工具

  1. Redis 自带工具

    • slowlog 命令
    • redis-cli --latency 命令
  2. 第三方监控工具

    • RedisInsight:可视化慢查询分析
    • Prometheus + Grafana:慢查询指标监控
    • RedisExporter:慢查询数据导出
  3. 自定义脚本

    • 使用 Python/Go 编写脚本分析慢查询日志
    • 结合 ELK Stack 进行集中日志分析

慢查询优化建议

命令层面优化

  1. 避免使用全键扫描命令

    • 使用 SCAN 替代 KEYS
    • 使用 HSCAN/SSCAN/ZSCAN 替代 HGETALL/SMEMBERS/ZRANGE
  2. 优化大键操作

    • 将大键拆分为多个小键
    • 使用分页查询(LRANGE key start end)
    • 避免一次性获取所有元素
  3. 合理使用事务和 Lua 脚本

    • 保持事务简短,避免长时间阻塞
    • 优化 Lua 脚本逻辑,减少执行时间
    • 使用 EVALSHA 替代 EVAL,减少网络传输

架构层面优化

  1. 分片存储

    • 使用 Redis Cluster 或 Codis 进行分片
    • 将大键分布到不同分片
  2. 读写分离

    • 只读命令路由到从节点
    • 从节点配置不同的慢查询阈值
  3. 缓存预热

    • 避免大量冷数据查询
    • 定期预热热点数据

慢查询监控与告警

监控指标

  1. 慢查询数量:单位时间内产生的慢查询日志条数
  2. 慢查询平均执行时间:慢查询的平均耗时
  3. 慢查询最长执行时间:单条慢查询的最大耗时
  4. 慢查询命令分布:不同类型慢查询命令的占比

告警配置

可以通过以下方式配置慢查询告警:

  1. 基于监控系统

    • Prometheus + Alertmanager:设置慢查询数量阈值告警
    • Zabbix:配置慢查询监控项和触发器
  2. 基于日志分析

    • ELK Stack:配置慢查询日志告警
    • Loki + Promtail:实时监控慢查询日志
  3. 自定义脚本

    • 编写脚本定期检查慢查询数量
    • 超过阈值时发送告警通知

慢查询分析实战

案例 1:KEYS 命令导致的性能问题

问题现象:Redis 实例 CPU 使用率突然升高,响应延迟增加

分析过程

  1. 查看慢查询日志,发现大量 KEYS user:* 命令
  2. 检查客户端代码,发现应用程序在定期执行全键扫描
  3. 分析业务逻辑,确认可以使用 SCAN 命令替代

解决方案

  • 将 KEYS user:* 替换为 SCAN 命令
  • 增加 SCAN 的 COUNT 参数,提高扫描效率
  • 优化业务逻辑,减少不必要的键扫描

案例 2:大哈希表查询导致的延迟

问题现象:HGETALL 命令执行时间超过 100 毫秒

分析过程

  1. 查看慢查询日志,确认 HGETALL large_hash 命令执行缓慢
  2. 使用 DEBUG OBJECT large_hash 查看哈希表大小
  3. 发现哈希表包含超过 10 万个字段

解决方案

  • 将大哈希表拆分为多个小哈希表(如按用户 ID 哈希)
  • 使用 HMGET 替代 HGETALL,只获取需要的字段
  • 考虑使用其他数据结构存储,如 Redis Streams

常见问题(FAQ)

Q1: 慢查询日志会影响 Redis 性能吗?

A1: 慢查询日志存储在内存中,写入操作是原子的,对 Redis 性能影响很小。但建议合理设置日志长度,避免占用过多内存。

Q2: 如何确定合适的慢查询阈值?

A2: 可以根据业务需求和 Redis 实例性能来调整。一般建议:

  • 生产环境:1-10 毫秒
  • 开发环境:100-1000 毫秒
  • 可以根据 P95/P99 延迟来设置

Q3: 慢查询日志为什么没有记录某些慢命令?

A3: 可能的原因包括:

  • 命令执行时间未超过慢查询阈值
  • 慢查询日志长度设置过小,被新日志覆盖
  • 命令在客户端发送到 Redis 服务器之前的耗时不计入

Q4: 如何分析历史慢查询日志?

A4: 可以通过以下方式:

  • 定期导出慢查询日志到文件
  • 使用 ELK Stack 或 Loki 进行集中存储和分析
  • 编写自定义脚本进行离线分析

Q5: 慢查询优化后如何验证效果?

A5: 可以通过以下指标验证:

  • 慢查询数量减少
  • Redis 实例 CPU 使用率降低
  • 命令响应延迟降低
  • 业务系统响应时间缩短

Q6: 哪些命令不会被记录到慢查询日志?

A6: 以下命令不会被记录:

  • SLOWLOG 相关命令
  • CONFIG 相关命令
  • 管理命令(如 SHUTDOWN、INFO)

Q7: 如何在 Redis Cluster 中分析慢查询?

A7: 需要在每个节点上分别查看慢查询日志,或者使用支持 Redis Cluster 的监控工具(如 RedisInsight)进行集中分析。

Q8: 慢查询日志中的执行时间包含网络延迟吗?

A8: 不包含。慢查询日志记录的是命令在 Redis 服务器端执行的时间,不包括网络传输时间。

Q9: 如何避免慢查询日志过多?

A9: 可以通过以下方式:

  • 合理设置慢查询阈值
  • 定期清理或导出慢查询日志
  • 优化应用程序,减少慢查询产生

Q10: 慢查询分析的最佳实践是什么?

A10: 最佳实践包括:

  • 合理配置慢查询日志参数
  • 定期分析慢查询日志
  • 建立慢查询监控和告警机制
  • 及时优化慢查询命令
  • 持续监控优化效果