*Redis 慢查询日志分析:SLOWLOG 配置与延迟排查
Redis 慢查询日志用于记录服务器端执行时间超过阈值的命令,是定位大 Key、高复杂度命令和阻塞操作的重要工具。本文说明 SLOWLOG 的配置、字段含义和分析方法,并区分慢命令、网络等待、连接池排队与持久化造成的延迟。
*SLOWLOG 记录的是什么
slowlog-log-slower-than 的单位是微秒。命令执行时间超过该阈值时,Redis 将命令加入内存中的慢查询日志。它主要统计命令在服务器执行阶段的时间,不包括完整的网络往返、客户端连接池等待和客户端反序列化时间。
因此会出现两种看似矛盾的情况:
- 客户端请求很慢,但 SLOWLOG 没有记录:瓶颈可能在网络、连接池、客户端 CPU、TLS 或服务器事件循环的其他阶段。
- SLOWLOG 中存在慢命令,但平均响应仍正常:少量大对象操作可能只影响尾延迟,需要结合 P95、P99 和发生时间判断。
SLOWLOG 不是完整访问日志,也不能替代应用侧链路追踪。
*配置慢查询日志
以下示例将阈值设为 10 毫秒,最多保留 256 条记录:
slowlog-log-slower-than 10000
slowlog-max-len 256
运行中可临时调整:
redis-cli CONFIG SET slowlog-log-slower-than 10000
redis-cli CONFIG SET slowlog-max-len 256
redis-cli CONFIG GET slowlog-log-slower-than slowlog-max-len
CONFIG SET 不等于已经写入配置文件。需要重启后仍生效时,应通过配置管理更新 redis.conf 或执行受控的 CONFIG REWRITE,并确认部署系统不会覆盖该修改。
将阈值设为 0 会记录所有命令,可能增加内存和观测开销;设为负数则禁用慢查询日志。生产环境不要长期用全量记录代替抽样监控。日志长度应结合命令量和排查窗口设置,过短时旧记录会被快速覆盖。
*读懂 SLOWLOG GET
redis-cli SLOWLOG LEN
redis-cli SLOWLOG GET 10
一条典型记录包含:
1) (integer) 18
2) (integer) 1763000000
3) (integer) 15240
4) 1) "HGETALL"
2) "user:1000"
5) "10.0.0.8:52344"
6) "app-worker"
各字段依次表示:
- 日志条目 ID,只在当前日志内容中用于识别条目。
- Unix 时间戳,用于和应用监控对齐。
- 执行耗时,单位为微秒;示例为 15.24 毫秒。
- 命令及参数,较长参数可能被截断。
- 客户端地址和端口,具体可用信息取决于版本与连接方式。
- 客户端名称,可通过 CLIENT SETNAME 设置,便于定位调用方。
日志可能包含业务键值、令牌或其他敏感参数。导出排障信息时应限制权限并脱敏,不要把完整输出直接贴到公共工单。
需要清理旧记录时可使用:
redis-cli SLOWLOG RESET
RESET 会删除当前实例的全部慢查询记录,执行前应先保存需要分析的内容。主节点和副本各自维护慢查询日志,检查多个节点时不要把单个节点的结果当作整个集群的结论。
*从慢命令定位根因
*检查命令复杂度和返回大小
以下命令在大数据量上容易产生高耗时或大响应:
| 操作 | 风险 | 常见改法 |
|---|---|---|
KEYS * |
遍历整个键空间,阻塞其他命令 | 使用 SCAN 游标分批处理 |
| HGETALL 大哈希 | 遍历并返回全部字段 | 用 HMGET 取所需字段,或用 HSCAN 分批 |
| SMEMBERS 大集合 | 返回全部成员并占用网络带宽 | 用 SSCAN,或重新设计数据模型 |
LRANGE 0 -1 长列表 |
返回整个列表 | 按页读取,限制列表长度 |
| 大范围 ZRANGE | 排序集合结果过大 | 限制范围,按需分页 |
| 大集合交并差 | 计算量随输入规模增长 | 缩小输入,离线计算或拆分任务 |
| 删除大对象 | 同步释放内存可能产生延迟 | 评估 UNLINK,并从根本上控制对象大小 |
SCAN 只是避免一次遍历整个键空间,不代表完整扫描没有成本。后台扫描仍应限速,并避免多个任务同时扫描同一实例。
*按命令汇总统计
redis-cli INFO commandstats
输出中的 calls 表示累计调用次数,usec 表示累计执行微秒数,usec_per_call 是累计平均值。平均值不能反映 P99,也无法单独说明某次故障;应在两个时间点之间计算增量,并与 QPS、慢查询和客户端指标对照。
INFO commandstats 的统计范围与实例生命周期和配置有关。使用 CONFIG RESETSTAT 会重置多项统计,不应只为临时观察而在生产中随意执行。
*检查大 Key 和热 Key
redis-cli --bigkeys
redis-cli MEMORY USAGE user:1000 SAMPLES 100
--bigkeys 适合发现线索,不等于完整内存审计。某个键耗时高也可能是访问频率过高,而不只是体积过大。具体治理见大 Key 与热 Key 排查。
*客户端慢但 SLOWLOG 为空时怎么查
| 现象 | 优先检查 | 建议证据 |
|---|---|---|
| 所有实例或接口同时变慢 | 网络、DNS、TLS、代理、宿主机 | 客户端分阶段耗时、网络重传、redis-cli --latency |
| 只有部分应用实例变慢 | 客户端 CPU、GC、连接池、序列化 | 池等待时间、线程/协程指标、进程 CPU |
| 高峰期排队,单命令很快 | 连接池过小或请求批量过大 | 获取连接耗时、池占用、Pipeline 批次大小 |
| 周期性延迟尖峰 | RDB/AOF、fork、磁盘和定时任务 |
latest_fork_usec、持久化状态、磁盘延迟 |
| 单个集群分片变慢 | 热点槽、节点资源、网络 | 分片级 QPS、CPU、带宽和键分布 |
| 故障后请求大量超时 | 重试风暴和连接重建 | 重试次数、退避、连接数、 rejected connections |
从客户端同网段测量 Redis 延迟:
redis-cli --latency -h 127.0.0.1 -p 6379
redis-cli --latency-history -h 127.0.0.1 -p 6379
本机测试和远程测试回答的问题不同。服务器本机延迟低而远程延迟高时,应继续检查网络路径、连接池和客户端,而不是直接调整 Redis 命令阈值。
*用延迟监控补充 SLOWLOG
Redis 延迟监控可记录执行过程中超过阈值的延迟事件。示例配置:
latency-monitor-threshold 100
该阈值单位是毫秒,设为 0 表示关闭。常用命令:
redis-cli LATENCY LATEST
redis-cli LATENCY HISTORY command
redis-cli LATENCY DOCTOR
LATENCY DOCTOR 提供诊断线索,但不会替代完整的指标和日志。可结合以下信息判断周期性尖峰:
redis-cli INFO persistence
redis-cli INFO memory
redis-cli INFO clients
redis-cli INFO stats
重点检查 latest_fork_usec、RDB/AOF 状态、内存压力、拒绝连接和客户端输出缓冲。不要只凭一项指标就修改内核参数或持久化策略。
*谨慎使用 MONITOR
redis-cli MONITOR
MONITOR 会持续输出服务器处理的命令,适合短时间、受控的调试。它可能明显增加服务器和网络开销,并暴露敏感参数。生产环境应优先使用 SLOWLOG、命令统计和客户端采样,避免长时间运行 MONITOR。
*建立可执行的排查流程
- 在客户端记录连接池等待、连接建立、命令发送、首字节响应和反序列化耗时。
- 按实例和命令统计 P50、P95、P99,而不是只看总体平均值。
- 保留慢查询日志,并将时间戳与应用错误、发布和定时任务对齐。
- 对慢命令检查复杂度、大 Key、返回值大小和访问频率。
- SLOWLOG 没有异常时,转向网络、连接池、持久化、操作系统和集群倾斜。
- 每次只调整一个变量,用相同数据和负载复测,确认优化没有牺牲数据安全。
*常见问题
*慢查询阈值设置为 10 毫秒是否通用
不是。阈值应根据业务延迟目标、命令基线和日志保留窗口确定。对低延迟在线服务,10 毫秒可能已经很高;对离线批处理,它可能产生过多记录。
*为什么 usec_per_call 很低,用户仍然超时
它主要是服务器端累计平均值,不包含所有客户端等待,也无法表达尾延迟。应检查分位延迟、连接池、网络和单次大结果处理。
*Pipeline 能消除慢查询吗
不能。Pipeline 主要减少网络往返,不会降低单条命令的算法复杂度。过大的 Pipeline 还可能占用输出缓冲并扩大单次等待,应控制批次规模。
相关阅读:Redis 性能优化指南、延迟问题排查、延迟监控、Pipeline 批量优化。