20 - 排错指南
排错指南
20.1 常见连接问题
问题一:无法连接 Redis
# 症状
redis-cli -h 192.168.1.100 ping
# Error: Connection refused
# 排查步骤
# 1. 检查 Redis 是否运行
systemctl status redis-server
ps aux | grep redis-server
# 2. 检查绑定地址
redis-cli CONFIG GET bind
# 如果是 127.0.0.1,外部无法访问
# 3. 检查端口
netstat -tlnp | grep 6379
ss -tlnp | grep 6379
# 4. 检查防火墙
sudo iptables -L -n | grep 6379
sudo ufw status
# 5. 检查 protected-mode
redis-cli CONFIG GET protected-mode
问题二:认证失败
# 症状
redis-cli SET key value
# (error) NOAUTH Authentication required.
# 解决
redis-cli -a yourpassword
# 或
redis-cli
AUTH yourpassword
# Redis 6.0+ ACL 错误
# (error) WRONGPASS invalid username-password pair or user is disabled.
ACL LIST # 检查用户列表
ACL WHOAMI # 查看当前用户
问题三:连接数过多
# 症状
# (error) ERR max number of clients reached
# 排查
redis-cli INFO clients | grep connected_clients
redis-cli CLIENT LIST | wc -l
# 解决
redis-cli CONFIG SET maxclients 20000
# 查看客户端连接详情
redis-cli CLIENT LIST
# id=1 addr=192.168.1.100:54321 fd=8 name= 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=ping
# 找出空闲时间最长的连接
redis-cli CLIENT LIST | awk '{print $4}' | sort -t= -k2 -nr | head -10
20.2 延迟问题排查
使用 redis-cli 诊断
# 1. 延迟测试
redis-cli --latency
# min: 0, max: 1, avg: 0.19 (264 samples)
# 2. 延迟历史
redis-cli --latency-history
# min: 0, max: 1, avg: 0.19 (132 samples) -- 15.00 seconds range
# 3. 延迟分布图
redis-cli --latency-dist
# 4. 内部延迟基准
redis-cli --intrinsic-latency 5
# 5 seconds of testing...
# 128 microseconds per call (best of 1000 calls)
慢查询分析
# 获取慢查询日志
redis-cli SLOWLOG GET 10
# 输出解析
# 1) 1) (integer) 1 # 日志 ID
# 2) (integer) 1715318400 # 时间戳
# 3) (integer) 15230 # 耗时(微秒)
# 4) 1) "KEYS" # 命令
# 2) "*"
# 5) "127.0.0.1:54321" # 客户端地址
# 慢查询日志长度
redis-cli SLOWLOG LEN
# 重置慢查询日志
redis-cli SLOWLOG RESET
# 检查最近的 fork 耗时
redis-cli INFO stats | grep latest_fork_usec
# latest_fork_usec:1500 ← 1.5ms,正常
延迟原因分析表
| 原因 | 症状 | 解决方案 |
|---|
| 慢命令 | SLOWLOG 中出现 O(N) 命令 | 避免 KEYS *、大 HGETALL |
| 大 Key | DEL/HDEL 阻塞 | 使用 UNLINK 异步删除 |
| fork 操作 | BGSAVE 期间延迟增大 | 减小实例内存、关闭 THP |
| 网络延迟 | 客户端到 Redis 延迟高 | 使用 Pipeline、就近部署 |
| 内存 swap | 延迟波动大 | 增加内存、设置 maxmemory |
| AOF fsync | appendfsync always | 改用 everysec |
| 客户端连接数过多 | 连接数 > 5000 | 使用连接池 |
| CPU 绑定问题 | 多核利用率不均 | 绑定 CPU 核心 |
延迟监控(LATENCY MONITOR)
# 启动延迟监控
redis-cli CONFIG SET latency-monitor-threshold 5 # 5ms
# 查看延迟事件
redis-cli LATENCY LATEST
# 1) 1) "command"
# 2) (integer) 1715318400
# 3) (integer) 15 # 延迟(毫秒)
# 4) (integer) 15 # 最大延迟
# 查看延迟历史
redis-cli LATENCY HISTORY command
# 延迟图形化(ASCII 图)
redis-cli LATENCY GRAPH command
20.3 内存问题排查
问题一:内存占用过高
# 1. 查看内存概况
redis-cli INFO memory
# used_memory_human:4.50G
# used_memory_peak_human:6.20G
# mem_fragmentation_ratio:1.25
# 2. 找出大 Key
redis-cli --bigkeys --i 0.1
# 3. 检查内存碎片率
redis-cli INFO memory | grep mem_fragmentation_ratio
# > 1.5 → 碎片严重,需要整理
# < 1.0 → 使用了 swap,非常危险
# 4. 开启碎片整理(Redis 4.0+)
redis-cli CONFIG SET activedefrag yes
# 5. 检查淘汰情况
redis-cli INFO stats | grep evicted_keys
# evicted_keys:0 → 无淘汰
# > 0 → 内存不足,正在淘汰
问题二:内存泄漏
# 症状:used_memory 持续增长,但数据量没有明显增加
# 排查步骤
# 1. 检查是否有 Key 没有设置过期时间
redis-cli DBSIZE
redis-cli INFO keyspace
# 2. 统计有 TTL 和无 TTL 的 Key 比例
python3 << 'EOF'
import redis
r = redis.Redis(decode_responses=True)
cursor = 0
with_ttl = 0
without_ttl = 0
while True:
cursor, keys = r.scan(cursor, count=100)
for key in keys:
if r.ttl(key) >= 0:
with_ttl += 1
elif r.ttl(key) == -1:
without_ttl += 1
if cursor == 0:
break
print(f"With TTL: {with_ttl}")
print(f"Without TTL: {without_ttl}")
EOF
# 3. 检查输出缓冲区
redis-cli CLIENT LIST | grep -oP 'omem=\d+' | sort -t= -k2 -nr | head -10
# omem=1048576 → 某个客户端的输出缓冲区占用 1MB
# 4. 检查复制缓冲区
redis-cli INFO replication | grep repl_backlog
问题三:内存使用不均(集群)
# 检查各节点内存使用
for port in 6371 6372 6373; do
echo "=== Node $port ==="
redis-cli -p $port INFO memory | grep used_memory_human
done
# 检查 Slot 分布
redis-cli CLUSTER SLOTS
# 检查是否有大 Key 导致分片不均
redis-cli --bigkeys
20.4 持久化问题排查
问题一:RDB 保存失败
# 检查最近一次 BGSAVE 状态
redis-cli INFO persistence | grep rdb_last_bgsave_status
# rdb_last_bgsave_status:err
# 查看日志
tail -100 /var/log/redis/redis-server.log | grep -i "rdb\|save\|error"
# 常见原因
# 1. 磁盘空间不足
df -h /var/lib/redis
# 2. 权限问题
ls -la /var/lib/redis/
# 3. fork 失败(内存不足)
redis-cli INFO memory | grep used_memory_human
free -h
# 确保系统有足够空闲内存(至少等于 Redis 内存占用)
# 4. 内核参数
cat /proc/sys/vm/overcommit_memory
# 应该为 1
sysctl vm.overcommit_memory=1
问题二:AOF 文件损坏
# 症状
# Bad file format reading the append only file
# 修复 AOF 文件
redis-check-aof --fix /var/lib/redis/appendonly.aof
# 验证
redis-check-aof /var/lib/redis/appendonly.aof
问题三:恢复速度慢
# 使用混合持久化(Redis 4.0+)
redis-cli CONFIG SET aof-use-rdb-preamble yes
# 下次 AOF 重写后的文件格式:
# [RDB 快照] + [增量 AOF 命令]
# 加载速度接近纯 RDB
20.5 复制问题排查
问题一:主从同步延迟
# 检查复制状态
redis-cli INFO replication
# master_link_status:up
# master_last_io_seconds_ago:1
# slave_repl_offset:12345
# master_repl_offset:12400
# 计算延迟
# 差值 = master_repl_offset - slave_repl_offset
# 55 字节延迟
# 检查复制积压缓冲区
redis-cli INFO replication | grep repl_backlog
# repl_backlog_active:1
# repl_backlog_size:1048576
# 如果延迟持续增大
# 1. 增大复制积压缓冲区
redis-cli CONFIG SET repl-backlog-size 268435456 # 256MB
# 2. 检查网络质量
ping -c 100 <slave_ip>
# 3. 检查从节点是否在执行慢查询
redis-cli -h <slave_ip> SLOWLOG GET 5
问题二:主从断开
# 症状
redis-cli INFO replication
# master_link_status:down
# master_last_io_seconds_ago:30
# 排查
# 1. 检查主节点是否存活
redis-cli -h <master_ip> PING
# 2. 检查密码
redis-cli CONFIG GET masterauth
# 3. 检查日志
grep -i "replica\|master\|error" /var/log/redis/redis-server.log
20.6 集群问题排查
问题一:集群状态异常
# 检查集群状态
redis-cli CLUSTER INFO
# cluster_state:fail
# cluster_slots_assigned:16384
# cluster_slots_ok:16000
# cluster_slots_pfail:384
# cluster_slots_fail:0
# 查看哪个节点有问题
redis-cli CLUSTER NODES | grep -v connected
# 修复 Slot 分配
redis-cli --cluster fix <node_ip>:<port>
问题二:节点下线
# 查看节点状态
redis-cli CLUSTER NODES
# 尝试重新加入
redis-cli CLUSTER MEET <new_node_ip> <port>
# 忘记已下线节点(15秒后自动)
redis-cli CLUSTER FORGET <node_id>
20.7 生产环境排错清单
| 问题类别 | 检查命令 | 正常范围 |
|---|
| 连接状态 | INFO clients | connected_clients < maxclients |
| 内存使用 | INFO memory | used_memory < maxmemory × 80% |
| 碎片率 | INFO memory | 1.0 - 1.5 |
| QPS | INFO stats | 根据容量规划 |
| 命中率 | INFO stats | > 80% |
| 慢查询 | SLOWLOG GET | 无 O(N) 大命令 |
| 淘汰数 | INFO stats | evicted_keys = 0 |
| 复制状态 | INFO replication | master_link_status = up |
| fork 耗时 | INFO stats | latest_fork_usec < 500000 |
| 持久化 | INFO persistence | last_bgsave_status = ok |
📌 业务场景
场景一:线上延迟突增
# 1. 检查慢查询
redis-cli SLOWLOG GET 10
# 2. 检查大 Key
redis-cli --bigkeys
# 3. 检查 fork 操作
redis-cli INFO stats | grep latest_fork_usec
# 4. 检查内存
redis-cli INFO memory | grep mem_fragmentation_ratio
场景二:内存告警
# 1. 检查内存使用
redis-cli INFO memory
# 2. 查找大 Key
redis-cli --bigkeys
# 3. 清理过期数据
redis-cli DBSIZE
# 4. 调整淘汰策略
redis-cli CONFIG SET maxmemory-policy allkeys-lru
场景三:主从不一致
# 1. 检查复制状态
redis-cli INFO replication
# 2. 手动触发同步
redis-cli -h <slave> REPLICAOF <master> 6379
# 3. 检查复制缓冲区
redis-cli INFO replication | grep repl_backlog
🔗 扩展阅读