如何定位redis阻塞
在 Redis 中定位阻塞原因需要系统性地排查可能导致性能瓶颈的环节。以下是详细的定位步骤和解决方案:
1. 检查 Redis 基础监控指标
(1) 延迟检测
使用
redis-cli
测量延迟:redis-cli --latency -h <host> -p <port> # 持续监控延迟 redis-cli --latency-history -i 5 # 每5秒采样一次
若延迟持续高于 1ms,可能存在阻塞。
通过
INFO
命令查看延迟统计:redis-cli INFO stats | grep instantaneous_ops_per_sec # 当前QPS redis-cli INFO stats | grep total_commands_processed # 总命令数
(2) 资源使用
- CPU 和内存:
redis-cli INFO memory | grep used_memory_human # 内存使用量 redis-cli INFO cpu | grep used_cpu_sys # 系统CPU占用
- 网络带宽:
使用
iftop
或nload
监控 Redis 端口的网络流量。
2. 分析 Redis 日志
(1) 错误日志路径
- 查看 Redis 配置文件
redis.conf
中的logfile
路径:tail -f /var/log/redis/redis-server.log
- 关键日志线索:
Background save terminated by signal
:持久化失败。OOM command not allowed
:内存不足。MISCONF Redis is configured to save RDB snapshots
:持久化配置错误。
3. 检查慢查询和大 Key
(1) 慢查询日志
- 查看慢查询记录:
redis-cli SLOWLOG GET 10 # 获取最近的10条慢查询
- 关注命令类型:
KEYS *
、FLUSHALL
、HGETALL
(大 Hash)、ZRANGE
(大 ZSet)。- 复杂 Lua 脚本(如长时间循环)。
(2) 大 Key 扫描
- 使用
--bigkeys
扫描:redis-cli --bigkeys # 找出大 Key
- 手动检查 Key 大小:
redis-cli MEMORY USAGE <key> # 查看指定 Key 的内存占用
4. 检查持久化操作
(1) RDB/AOF 持久化状态
- 查看持久化进程:
redis-cli INFO persistence | grep -E "rdb_bgsave_in_progress|aof_rewrite_in_progress"
rdb_bgsave_in_progress:1
表示 RDB 持久化中。aof_rewrite_in_progress:1
表示 AOF 重写中。
(2) Fork 阻塞问题
- 日志中检查
fork
耗时:grep "Background saving terminated" /var/log/redis/redis-server.log
- 若
fork
操作耗时过长(如超过 1s),可能是内存过大或系统配置问题。
- 若
- 优化建议:
- 使用物理机而非虚拟机(减少内存页拷贝开销)。
- 调整
vm.overcommit_memory=1
(允许超额分配内存)。
5. 分析客户端连接
(1) 客户端列表
- 查看所有客户端连接:
redis-cli CLIENT LIST # 显示所有连接的客户端信息
- 关注字段:
idle
:连接空闲时间(若大量连接空闲,可能是客户端未释放连接)。cmd
:最近执行的命令。name
:客户端名称(定位问题客户端)。
(2) 阻塞命令检测
- 查找阻塞命令:
redis-cli CLIENT LIST | grep flags=B # 查找阻塞状态的客户端
- 常见阻塞命令:
BLPOP
、BRPOP
、BRPOPLPUSH
、SUBSCRIBE
。
- 常见阻塞命令:
6. 内存与淘汰策略
(1) 内存使用检查
- 查看内存状态:
redis-cli INFO memory | grep -E "used_memory|maxmemory|mem_fragmentation_ratio"
mem_fragmentation_ratio > 1.5
表示内存碎片严重。used_memory >= maxmemory
会触发键淘汰(LRU/LFU)。
(2) 键淘汰监控
- 查看淘汰统计:
redis-cli INFO stats | grep evicted_keys # 被淘汰的键数量
- 若
evicted_keys
持续增长,需扩容内存或优化数据。
- 若
7. 网络与系统级排查
(1) 网络延迟
- 使用
ping
和tcpdump
:ping <redis-host> # 检查基础网络延迟 tcpdump -i eth0 port 6379 -w redis.pcap # 抓包分析网络问题
(2) 系统资源限制
- 检查文件描述符限制:
ulimit -n # 查看当前限制 grep "Max open files" /etc/security/limits.conf # 系统配置
- Redis 需要足够高的文件描述符限制(建议
10032
)。
- Redis 需要足够高的文件描述符限制(建议
8. 高级工具与调试
(1) 使用 perf
分析性能
- 生成火焰图:
perf record -p <redis-pid> -g -- sleep 30 # 采样30秒 perf script | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > redis.svg
(2) GDB 调试(谨慎使用)
- 附加到 Redis 进程:
sudo gdb -p <redis-pid>
- 输入
bt
查看堆栈跟踪(需 Redis 编译时保留调试符号)。
- 输入
常见阻塞场景与解决方案
阻塞原因 | 现象 | 解决方案 |
---|---|---|
慢查询 | 高延迟,SLOWLOG 中有耗时命令 |
优化复杂命令,拆分大 Key,使用 SCAN 替代 KEYS 。 |
大 Key 操作 | 单次操作耗时长,内存占用高 | 拆分 Key(如 Hash 分片),使用 Pipeline 减少网络开销。 |
持久化 Fork 阻塞 | RDB/AOF 重写期间延迟飙升 | 升级机器内存,关闭 THP(echo never > /sys/kernel/mm/transparent_hugepage/enabled )。 |
内存不足 | OOM 错误,evicted_keys 增加 |
扩容内存,优化数据结构,设置合理的 maxmemory-policy 。 |
客户端阻塞命令 | 客户端连接堆积,CLIENT LIST 显示阻塞状态 |
检查客户端代码,避免使用 BLPOP 超时过长,改用非阻塞方案。 |
网络拥堵 | 高网络延迟,带宽占满 | 优化客户端批量操作,升级网络带宽,使用 Redis 集群分散流量。 |
总结
- 监控先行:通过
INFO
、SLOWLOG
、CLIENT LIST
快速定位异常点。 - 日志分析:检查 Redis 日志中的错误和警告信息。
- 资源检查:排查 CPU、内存、网络、文件描述符等系统限制。
- 客户端审查:分析客户端行为,避免阻塞命令和连接泄漏。
- 工具辅助:使用
perf
、tcpdump
、GDB
深入诊断复杂问题。