Redis 监控与故障排查
在生产环境中,没有监控的 Redis 是一枚定时炸弹。本章介绍如何实时掌握 Redis 的健康状况,以及在出现问题时如何排查和解决。
核心监控命令 INFO
INFO 是 Redis 最权威的状态输出,包含了内存、连接、CPU 等 10 个分类:
内存信息
127.0.0.1:6379> INFO memory
# 重点指标
used_memory_human: 1.5G # 实际使用内存
used_memory_rss: 2.0G # 操作系统分配给 Redis 的内存(包含碎片)
mem_fragmentation_ratio: 1.33 # 碎片率(建议 1.0~1.5 之间)
maxmemory: 4G # 最大内存限制
maxmemory_policy: allkeys-lru # 淘汰策略
客户端连接信息
127.0.0.1:6379> INFO clients
# 重点指标
connected_clients: 100 # 当前连接数
blocked_clients: 5 # 处于阻塞状态的客户端数(如 BLPOP)
tracking_clients: 0 # 开启客户端缓存的连接数
clients_in_timeout_table: 0 # 在超时表中的客户端数
统计信息
127.0.0.1:6379> INFO stats
# 重点指标
total_connections_received: 10000 # 历史连接总数
total_commands_processed: 1000000 # 历史命令总数
instantaneous_ops_per_sec: 5000 # 每秒处理命令数
total_net_input_bytes: 1GB # 网络输入总字节
total_net_output_bytes: 2GB # 网络输出总字节
keyspace_hits: 800000 # 缓存命中次数
keyspace_misses: 200000 # 缓存未命中次数
复制信息
127.0.0.1:6379> INFO replication
# 重点指标
role: master # 角色
connected_slaves: 2 # 连接的从库数量
slave0: ip=192.168.1.101,port=6379,state=online,offset=12345,lag=0
master_repl_offset: 12345 # 主库复制偏移量
慢查询日志 SLOWLOG
当 Redis 变慢时,首选工具就是 SLOWLOG。
配置慢查询日志
# redis.conf
slowlog-log-slower-than 10000 # 超过 10 毫秒记录(微秒单位)
slowlog-max-len 128 # 日志最大容量
# 运行时修改
127.0.0.1:6379> CONFIG SET slowlog-log-slower-than 10000
OK
127.0.0.1:6379> CONFIG SET slowlog-max-len 256
OK
查看慢查询日志
# 获取最新的 10 条慢查询
127.0.0.1:6379> SLOWLOG GET 10
# 输出示例
1) 1) (integer) 1 # 日志 ID
2) (integer) 1609459200 # 时间戳
3) (integer) 15000 # 执行时间(微秒)
4) 1) "KEYS" # 命令
2) "*"
5) "127.0.0.1:54321" # 客户端地址
6) "user1" # 客户端名称
# 获取日志当前长度
127.0.0.1:6379> SLOWLOG LEN
(integer) 5
# 重置日志
127.0.0.1:6379> SLOWLOG RESET
OK
常见慢查询原因
| 命令 | 问题 | 解决方案 |
|---|---|---|
KEYS * | 阻塞遍历所有键 | 使用 SCAN |
HGETALL 大 Hash | 大键操作 | 拆分键或使用 HSCAN |
ZRANGE 大 ZSet | 大范围查询 | 分批查询 |
DEL 大键 | 阻塞删除 | 使用 UNLINK |
命令监控 MONITOR
MONITOR 可以实时打印服务器接收到的所有请求:
127.0.0.1:6379> MONITOR
OK
1727000000.123 [0 127.0.0.1:5432] "GET" "user:123"
1727000000.234 [0 127.0.0.1:5433] "SET" "counter" "1"
1727000000.345 [0 127.0.0.1:5434] "INCR" "counter"
注意:MONITOR 会消耗大量 CPU,仅用于非高负载环境的短时间调试。
延迟追踪 LATENCY
Redis 提供了专门的延迟分析框架。
配置延迟监控
# 设置采样阈值(毫秒)
127.0.0.1:6379> CONFIG SET latency-monitor-threshold 100
OK
查看延迟事件
# 查看最近的延迟事件
127.0.0.1:6379> LATENCY LATEST
1) 1) "command"
2) (integer) 1609459200 # 时间戳
3) (integer) 150 # 延迟(毫秒)
4) (integer) 200 # 最大延迟
# 查看延迟直方图
127.0.0.1:6379> LATENCY GRAPH command
延迟事件类型
| 事件 | 说明 |
|---|---|
command | 命令执行延迟 |
fork | fork 操作延迟 |
rdb-unlink-temp-file | RDB 临时文件删除延迟 |
aof-write-pending-fsync | AOF 写入延迟 |
aof-rewrite-diff-write | AOF 重写差异写入延迟 |
性能测试 redis-benchmark
内置压测工具,评估当前服务器能抗住多少 QPS。
基本使用
# 测试 100 个并发连接,10 万次请求
redis-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 100000
# 只测试特定的 SET/GET 命令
redis-benchmark -t set,get -q -n 100000
# 测试指定数据大小
redis-benchmark -t set -d 1000 -n 100000
# 使用 Pipeline
redis-benchmark -t set,get -P 10 -n 100000
输出解读
====== SET ======
100000 requests completed in 1.23 seconds
100 parallel clients
3 bytes payload
keep alive: 1
99.95% <= 1 milliseconds
100.00% <= 2 milliseconds
81300.81 requests per second
关键指标:
- requests per second:每秒请求数(QPS)
<= 1 milliseconds:响应时间分布
客户端管理
查看客户端列表
127.0.0.1:6379> CLIENT LIST
# 输出示例
id=1 addr=127.0.0.1:54321 fd=5 name= user=default age=100 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=set
# 字段说明
# id: 客户端 ID
# addr: 客户端地址
# name: 客户端名称
# age: 连接存活时间(秒)
# idle: 空闲时间(秒)
# qbuf: 查询缓冲区大小
# omem: 输出缓冲区内存使用
# cmd: 最后执行的命令
管理客户端
# 设置客户端名称
127.0.0.1:6379> CLIENT SETNAME myapp
# 获取当前客户端信息
127.0.0.1:6379> CLIENT INFO
# 断开指定客户端
127.0.0.1:6379> CLIENT KILL 127.0.0.1:54321
# 断开所有空闲超过 60 秒的客户端
127.0.0.1:6379> CLIENT KILL IDLE 60
生产级监控方案
Prometheus + Grafana
对于中大型系统,建议使用 Redis Exporter + Prometheus + Grafana:
1. 部署 Redis Exporter
# docker-compose.yml
version: '3.8'
services:
redis_exporter:
image: oliver006/redis_exporter:latest
ports:
- "9121:9121"
environment:
- REDIS_ADDR=redis://redis:6379
- REDIS_PASSWORD=your_password
2. Prometheus 配置
# prometheus.yml
scrape_configs:
- job_name: 'redis'
static_configs:
- targets: ['redis_exporter:9121']
3. 核心监控指标
| 指标 | 说明 | 告警阈值建议 |
|---|---|---|
redis_up | 服务是否存活 | = 0 |
redis_connected_clients | 当前连接数 | > maxclients * 0.8 |
redis_memory_used_bytes | 内存使用量 | > maxmemory * 0.9 |
redis_keyspace_hits_total | 缓存命中次数 | - |
redis_keyspace_misses_total | 缓存未命中次数 | - |
redis_commands_processed_total | 命令处理总数 | - |
redis_connected_slaves | 从库连接数 | < 预期值 |
4. 缓存命中率计算
缓存命中率 = keyspace_hits / (keyspace_hits + keyspace_misses)
建议保持在 80% 以上。
监控脚本示例
import redis
import time
def monitor_redis(host='localhost', port=6379, interval=60):
"""Redis 监控脚本"""
r = redis.Redis(host=host, port=port, decode_responses=True)
while True:
try:
# 获取信息
info = r.info()
memory = r.info('memory')
stats = r.info('stats')
# 计算缓存命中率
hits = stats.get('keyspace_hits', 0)
misses = stats.get('keyspace_misses', 0)
hit_rate = hits / (hits + misses) * 100 if (hits + misses) > 0 else 0
# 输出监控数据
print(f"""
========== Redis 监控 ==========
时间: {time.strftime('%Y-%m-%d %H:%M:%S')}
连接数: {info['connected_clients']}
内存使用: {memory['used_memory_human']} / {memory.get('maxmemory_human', 'unlimited')}
碎片率: {memory['mem_fragmentation_ratio']:.2f}
QPS: {stats['instantaneous_ops_per_sec']}
缓存命中率: {hit_rate:.2f}%
Key 数量: {sum(info.get(f'db{i}', {}).get('keys', 0) for i in range(16))}
================================
""")
except Exception as e:
print(f"监控异常: {e}")
time.sleep(interval)
if __name__ == '__main__':
monitor_redis()
故障排查套路
1. 命令变慢
排查步骤:
- 查看
SLOWLOG找到慢命令 - 检查是否使用
KEYS、大键操作 - 检查内存是否达到 maxmemory
- 检查是否有大量过期键
# 查看慢查询
SLOWLOG GET 10
# 检查内存
INFO memory
# 检查过期键
INFO keyspace
2. 连接数过多
排查步骤:
- 查看
INFO clients确认连接数 - 使用
CLIENT LIST找到异常客户端 - 检查应用是否正确使用连接池
# 查看连接数
INFO clients
# 找到空闲连接
CLIENT LIST | grep "idle="
# 断开空闲连接
CLIENT KILL IDLE 60
3. 内存占用过高
排查步骤:
- 查看
INFO memory确认内存使用 - 使用
redis-cli --bigkeys查找大键 - 检查是否设置了 maxmemory 和淘汰策略
- 检查内存碎片率
# 查看内存
INFO memory
# 查找大键
redis-cli --bigkeys
# 查看单个键内存
MEMORY USAGE mykey
4. CPU 使用率过高
排查步骤:
- 检查是否在执行慢命令
- 检查是否有大量请求
- 检查是否开启了
MONITOR
# 检查 QPS
INFO stats | grep instantaneous
# 检查是否有 MONITOR
CLIENT LIST | grep monitor
5. 主从同步延迟
排查步骤:
- 查看
INFO replication检查 offset - 检查网络延迟
- 检查从库负载
# 查看复制信息
INFO replication
# 检查同步偏移量差值
# master_repl_offset 与 slave 的 offset 差值
监控检查清单
每日检查
- 服务是否正常运行
- 内存使用率是否正常
- 连接数是否异常
- 是否有慢查询告警
每周检查
- 缓存命中率趋势
- 大键扫描
- 持久化状态
- 主从同步状态
每月检查
- Redis 版本更新
- 配置参数优化
- 容量规划评估
- 故障演练
小结
本章我们学习了:
- INFO 命令:内存、客户端、统计等核心指标
- SLOWLOG:慢查询日志配置和查看
- MONITOR:实时命令监控
- LATENCY:延迟追踪和分析
- redis-benchmark:性能测试工具
- 客户端管理:查看和管理客户端连接
- Prometheus + Grafana:生产级监控方案
- 故障排查:常见问题的排查思路
练习
- 配置慢查询日志,并分析慢查询原因
- 使用 redis-benchmark 测试 Redis 性能
- 编写一个 Redis 监控脚本
- 模拟一个性能问题并排查解决