Redis 慢查询分析与优化
参考书籍 : https://weread.qq.com/web/reader/d5432be0813ab98b6g0133f5kd8232f00235d82c8d161fb2
以下从配置参数、耗时细分、分析工具、优化策略四个维度深入解析 Redis 慢查询问题,结合实战调优建议,帮助开发者精准定位并优化性能瓶颈。
一、慢查询核心配置参数
Redis 慢查询功能通过两个关键参数控制,直接影响日志记录范围和存储容量:
-
slowlog-log-slower-than
-
功能:设定命令执行时间的阈值(单位:微秒),超过此值的命令会被记录。
-
默认值:10000 微秒(10 毫秒),建议高并发场景调整为 1000 微秒(1 毫秒) 。
-
特殊值:
-
0
:记录所有命令(调试用)。 - 负值:禁用慢查询日志。
-
-
-
slowlog-max-len
- 功能:定义慢查询日志列表的最大长度(先进先出队列)。
- 默认值:128 条,生产环境建议调至 1000 条以上,避免关键日志被覆盖。
配置示例:
# 动态设置(临时生效)
CONFIG SET slowlog-log-slower-than 1000
CONFIG SET slowlog-max-len 1000 # 持久化到配置文件(需重启)
slowlog-log-slower-than 1000
slowlog-max-len 1000
二、耗时细分与瓶颈定位
Redis 命令执行全流程耗时可拆分为以下阶段:
-
网络传输(客户端到服务端):
- 网络延迟或丢包可能导致客户端感知的耗时增加,但不记录在慢查询日志中。
- 排查工具:
ping
、traceroute
或监控工具(如 Prometheus)。
-
命令排队(Redis 内部队列):
- 单线程架构下,若并发请求过高,命令需排队等待执行。
- 排队时间不纳入慢查询统计,但可能导致客户端超时。
-
命令执行(核心耗时):
- 实际执行命令的耗时,由慢查询日志的
duration
字段记录(单位:微秒)。 - 高复杂度命令(如
KEYS
、SORT
)或 BigKey 操作是主要瓶颈。
- 实际执行命令的耗时,由慢查询日志的
-
结果返回(服务端到客户端):
- 网络传输时间同样不计入慢查询日志,但可能影响客户端体验。
三、慢查询分析工具
-
内置命令:
-
**
SLOWLOG GET [n]
**:获取最近 n 条慢查询日志,含时间戳、耗时、具体命令。127.0.0.1:6379> SLOWLOG GET 2 1) 1) (integer) 12345 # 日志ID 2) (integer) 1680000000 # 时间戳 3) (integer) 15000 # 耗时(微秒) 4) 1) "SORT" # 命令及参数 2) "mylist"
-
**
SLOWLOG LEN
**:查看当前慢查询日志数量。 -
**
SLOWLOG RESET
**:清空日志列表。
-
-
监控工具:
-
**
INFO COMMANDSTATS
**:统计所有命令的执行次数和总耗时,定位高频耗时命令。参数介绍:
截图中每一项均以
cmdstat_<命令名>
开头,代表对应 Redis 命令的执行统计信息,各参数含义如下:参数名 含义 calls
该命令的总执行次数。 usec
该命令所有执行耗时的总和(单位:微秒,μs)。 usec_per_call
该命令的平均执行时间(单位:微秒,μs),即 usec ÷ calls
。 rejected_calls
该命令被拒绝执行的次数(如权限不足、命令被禁用等情况)。 failed_calls
该命令执行过程中失败的次数(如参数错误、执行逻辑异常等)。 以
cmdstat_ttl:calls=304,usec=3064,usec_per_call=10.08,rejected_calls=1,failed_calls=0
为例:-
TTL
命令共执行304
次,总耗时3064
微秒,平均每次耗时10.08
微秒,被拒绝执行1
次,执行失败0
次。
其他项(如
cmdstat_auth
、cmdstat_set
等)均遵循此格式,分别对应各自命令的统计数据,可据此分析命令的执行频率、性能及异常情况。 -
-
**
MONITOR
**:实时捕获所有命令(慎用,可能引发性能问题)。 -
第三方工具:Prometheus + Grafana 实现可视化监控。 后续研究
-
四、优化策略与实战建议
-
规避高复杂度命令:
-
替代方案:
- 用
SCAN
代替KEYS
遍历键。 - 客户端实现排序,避免
SORT
命令处理大数据集。
- 用
-
分页处理:对大型集合使用
LRANGE
分批次获取数据。
-
-
BigKey 治理:
-
拆分存储:将大 Hash/List 拆分为多个子键(如
user:1001:logs_part1
)。 -
渐进式删除:通过 Lua 脚本分批次删除 BigKey,避免阻塞。
-- 分批次删除大列表 local key = KEYS[1] for i = 1, 1000 do redis.call("LPOP", key) end
-
-
配置调优:
- 内存管理:设置
maxmemory
和淘汰策略(如allkeys-lru
)。 - 集群分片:使用 Redis Cluster 分散负载,缓解单节点压力。
- 内存管理:设置
五、调优最佳实践
-
定期日志分析:
- 每日检查慢查询日志,识别高频耗时命令。
- 结合
INFO COMMANDSTATS
验证优化效果。
-
阈值动态调整:
- 业务高峰期临时降低
slowlog-log-slower-than
(如 500 微秒),捕捉潜在问题。
- 业务高峰期临时降低
-
日志持久化:
- 定期将慢查询日志导出到外部存储(如 Elasticsearch),便于长期分析。
总结
通过合理配置 slowlog-log-slower-than
和 slowlog-max-len
,结合 SLOWLOG GET
和监控工具,可精准定位 Redis 性能瓶颈。优化核心在于规避高复杂度命令、治理 BigKey、动态调整配置及利用集群技术。定期分析日志与监控数据,是保障 Redis 高性能运行的关键。