Redis 线上故障案例分析:从救火到防火的实战指南
🔥 Redis 线上故障案例分析:从救火到防火的实战指南
文章目录
- 🔥 Redis 线上故障案例分析:从救火到防火的实战指南
- 🚨 一、前言:Redis 故障的蝴蝶效应
- ⚡ 高并发系统的脆弱性
- 📊 故障影响统计
- 💥 二、案例一:内存爆炸故障
- 🚨 问题表现
- 🔍 原因分析
- 🛠️ 解决方案
- 🛡️ 预防措施
- ⏱️ 三、案例二:延迟抖动故障
- 🚨 问题表现
- 🔍 原因分析
- 🛠️ 解决方案
- 🛡️ 预防措施
- 🔄 四、案例三:主从复制异常
- 🚨 问题表现
- 🔍 原因分析
- 🛠️ 解决方案
- 🛡️ 预防措施
- 🛡️ 五、总结:运维最佳实践
- 📋 Redis 运维清单
- 🚨 应急响应流程
- 📊 监控体系建设
🚨 一、前言:Redis 故障的蝴蝶效应
⚡ 高并发系统的脆弱性
在现代分布式系统中,Redis 作为核心缓存和数据存储组件,一旦出现故障,其影响会像多米诺骨牌一样迅速扩散:
📊 故障影响统计
根据对 100+ 线上故障的分析,Redis 问题主要集中在:
-
内存问题(45%):OOM、大Key、内存碎片
-
性能问题(30%):延迟抖动、慢查询
-
高可用问题(25%:主从复制、集群故障
💥 二、案例一:内存爆炸故障
🚨 问题表现
# 错误日志示例
[ERROR] OOM command not allowed when used memory > 'maxmemory'
[WARNING] Overcommit memory is disabled
[CRITICAL] # Can't save in background: fork: Cannot allocate memory
系统症状:
-
Redis 进程突然崩溃
-
客户端收到 OOM错误响应
-
服务器内存使用率 100%
-
Fork 进程因内存不足失败
🔍 原因分析
1. 大Key问题:
# 查找大Key(生产环境慎用)
redis-cli --bigkeys# 示例输出
[00.00%] Biggest string found so far 'product:1001:info' with 1024 bytes
[12.34%] Biggest hash found so far 'user:2001:cart' with 100000 fields
2. 内存配置不当:
# 错误配置:未设置最大内存
# maxmemory 0 # 默认无限制# 错误配置:淘汰策略为noeviction
maxmemory-policy noeviction
3. 持久化叠加:
🛠️ 解决方案
紧急处理:
# 1. 临时扩容
redis-cli config set maxmemory 4gb# 2. 手动触发淘汰
redis-cli memory purge# 3. 删除大Key(分批次)
redis-cli hscan "user:2001:cart" 0 count 100 | xargs redis-cli hdel
根本解决:
# redis.conf 优化配置
maxmemory 2gb
maxmemory-policy allkeys-lru
maxmemory-samples 5# 禁用危险命令
rename-command FLUSHALL ""
rename-command FLUSHDB ""
rename-command KEYS ""
🛡️ 预防措施
监控体系:
# 内存监控脚本
#!/bin/bash
used_memory=$(redis-cli info memory | grep used_memory: | cut -d: -f2)
max_memory=$(redis-cli info memory | grep maxmemory: | cut -d: -f2)
usage_ratio=$((used_memory * 100 / max_memory))if [ $usage_ratio -gt 80 ]; thenecho "内存告警: 使用率 ${usage_ratio}%"# 发送告警通知
fi
定期巡检:
# 每周执行大Key分析
redis-cli --bigkeys -i 0.1 | grep -E "(Biggest|bytes|fields)" > bigkey_report.txt# 内存碎片检查
redis-cli info memory | grep mem_fragmentation_ratio
⏱️ 三、案例二:延迟抖动故障
🚨 问题表现
# 慢查询日志
[WARNING] Slow query: 125ms - HGETALL user:session:*
[WARNING] Slow query: 256ms - KEYS pattern:*
系统症状:
-
客户端请求超时率飙升
-
P99 延迟从 5ms 上升到 500ms+
-
CPU 使用率异常增高
-
网络流量正常但响应缓慢
🔍 原因分析
1. 慢查询攻击:
// 错误代码:使用KEYS命令
Set<String> keys = redisTemplate.keys("user:session:*"); // O(n)复杂度// 正确代码:使用SCAN
Cursor<String> cursor = redisTemplate.scan(ScanOptions.scanOptions().match("user:session:*").count(100).build()
);
2. 持久化阻塞:
# RDB持久化期间的延迟峰值
[INFO] DB saved on disk
[INFO] RDB: 524 MB of memory used by copy-on-write
3. CPU 竞争:
# 查看CPU使用情况
top -p $(pgrep redis-server)# 发现AOF重写进程占用高CPU
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1234 redis 20 0 10.4g 2.1g 1.2g S 89.3 6.7 100:30.79 redis-server
5678 redis 20 0 10.4g 2.1g 1.2g R 95.6 6.7 50:20.45 redis-aof-rewrite
🛠️ 解决方案
紧急处理:
# 1. 终止慢查询
redis-cli client list | grep cmd=keys | awk '{print $2}' | cut -d= -f2 | xargs redis-cli client kill# 2. 调整持久化策略
redis-cli config set appendonly no
redis-cli config set save ""
性能优化:
// 使用Pipeline批量操作
List<Object> results = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {for (int i = 0; i < 1000; i++) {connection.stringCommands().set(("key:" + i).getBytes(),("value:" + i).getBytes());}return null;}
);
🛡️ 预防措施
慢查询监控:
# redis.conf 配置
slowlog-log-slower-than 10000 # 记录超过10ms的查询
slowlog-max-len 128 # 保存128条慢日志
定期分析:
# 查看慢查询日志
redis-cli slowlog get# 输出示例
1) 1) (integer) 1234 # 日志ID2) (integer) 1685098765 # 时间戳3) (integer) 125000 # 执行时间(微秒)4) 1) "KEYS" # 命令2) "user:session:*"
🔄 四、案例三:主从复制异常
🚨 问题表现
# 复制错误日志
[ERROR] Unexpected reply to PSYNC from master: -Full resync needed
[WARNING] Disconnecting timedout replica: 10.0.0.2:6380
[CRITICAL] Master does not support PSYNC, full resync needed
系统症状:
-
从节点数据严重滞后
-
主从连接频繁断开重连
-
全量复制频繁发生
-
客户端读取到过期数据
🔍 原因分析
- 复制缓冲区不足:
# 默认配置可能不足
client-output-buffer-limit replica 256mb 64mb 60
- 网络抖动:
# 查看复制状态
redis-cli info replication# 输出显示频繁断开
master_link_down_since_seconds: 30
master_link_status: down
- 版本不兼容:
# 主从版本不一致
主节点: Redis 7.0.10
从节点: Redis 6.2.5 # 不支持某些PSYNC特性
🛠️ 解决方案
紧急处理:
# 1. 重启复制进程
redis-cli -p 6380 replicaof no one
redis-cli -p 6380 replicaof 10.0.0.1 6379# 2. 调整缓冲区大小
redis-cli config set client-output-buffer-limit "replica 1024mb 256mb 300"
根本解决:
# 优化复制配置
repl-backlog-size 512mb
repl-backlog-ttl 3600
client-output-buffer-limit replica 1024mb 256mb 300
min-replicas-to-write 1
min-replicas-max-lag 10
🛡️ 预防措施
复制监控体系:
#!/bin/bash
# 复制健康检查脚本
lag=$(redis-cli info replication | grep master_repl_offset | cut -d: -f2)
slave_lag=$(redis-cli info replication | grep repl_offset | cut -d: -f2)
lag_difference=$((lag - slave_lag))if [ $lag_difference -gt 1048576 ]; thenecho "复制延迟告警: ${lag_difference} bytes"# 发送告警通知
fi
🛡️ 五、总结:运维最佳实践
📋 Redis 运维清单
检查项 | 频率 | 标准 | 工具 |
---|---|---|---|
内存使用 | 实时监控 | <80% maxmemory | info memory |
持久化状态 | 每日 | 最近备份成功 | info persistence |
复制状态 | 实时监控 | 主从延迟<1MB | info replication |
慢查询 | 每周 | 无>100ms查询 | slowlog get |
连接数 | 实时监控 | <maxclients的80% | info clients |
Key数量 | 每日 | 无异常增长 | dbsize |
🚨 应急响应流程
📊 监控体系建设
关键监控指标:
# 内存指标
used_memory_rss
mem_fragmentation_ratio
evicted_keys# 性能指标
instantaneous_ops_per_sec
slowlog_len
latency_percentiles# 高可用指标
connected_slaves
master_repl_offset
replica_repl_offset