前言
Redis用着用着总会遇到各种问题:连接超时、内存暴涨、主从不同步、缓存雪崩...
这篇整理Redis常见问题的排查思路和解决方案,线上出问题时能快速定位。
一、连接问题
1.1 连接超时
现象 :客户端报Connection timed out或JedisConnectionException
排查步骤:
bash
# 1. 检查Redis是否存活
redis-cli ping
# 2. 检查端口是否监听
ss -tlnp | grep 6379
# 3. 检查连接数
redis-cli info clients
# connected_clients:150 ← 当前连接数
# 4. 查看最大连接数配置
redis-cli config get maxclients
# maxclients: 10000
# 5. 检查是否有慢查询阻塞
redis-cli slowlog get 10
常见原因:
- 连接数打满
bash
# 查看客户端列表
redis-cli client list
# 找到空闲时间长的连接
redis-cli client list | awk -F'[ =]' '{print $4, $10}' | sort -k2 -rn | head
解决:增大maxclients,或检查客户端连接池配置。
- 网络问题
bash
# 测试网络延迟
redis-cli --latency
# 持续监控
redis-cli --latency-history
- Redis阻塞
bash
# 检查阻塞操作
redis-cli info stats | grep blocked
1.2 连接被拒绝
现象 :Connection refused
bash
# 检查绑定地址
redis-cli config get bind
# 如果是 127.0.0.1,远程无法连接
# 修改配置
# /etc/redis/redis.conf
bind 0.0.0.0 # 或具体IP
# 检查防火墙
iptables -L -n | grep 6379
firewall-cmd --list-ports | grep 6379
二、内存问题
2.1 内存暴涨
排查步骤:
bash
# 1. 查看内存使用
redis-cli info memory
# used_memory_human: 2.5G
# used_memory_peak_human: 3.1G
# maxmemory_human: 4G
# 2. 查看各类型key的内存占用
redis-cli memory doctor
# 3. 分析大key
redis-cli --bigkeys
# 4. 扫描特定前缀的key数量
redis-cli keys "user:*" | wc -l
# 注意:生产环境用 scan 代替 keys
redis-cli scan 0 match "user:*" count 1000
找出大key:
bash
# 分析RDB文件(推荐)
# 安装 rdb-tools
pip install rdbtools python-lzf
# 导出大key报告
rdb -c memory /var/lib/redis/dump.rdb --bytes 10240 -f memory.csv
或者用Redis自带命令:
bash
# 查看某个key的内存占用
redis-cli memory usage mykey
# 批量分析
redis-cli --bigkeys -i 0.1 # 每100ms扫描一次,降低影响
2.2 内存淘汰
现象 :写入失败,报OOM command not allowed
bash
# 查看淘汰策略
redis-cli config get maxmemory-policy
# volatile-lru / allkeys-lru / noeviction 等
# 查看淘汰统计
redis-cli info stats | grep evicted
# evicted_keys: 12345
淘汰策略说明:
| 策略 | 说明 |
|---|---|
| noeviction | 不淘汰,内存满了报错 |
| volatile-lru | 淘汰有过期时间的key(LRU) |
| allkeys-lru | 淘汰所有key(LRU) |
| volatile-ttl | 淘汰TTL最短的key |
| volatile-random | 随机淘汰有过期时间的key |
| allkeys-random | 随机淘汰 |
建议配置:
bash
# redis.conf
maxmemory 4gb
maxmemory-policy allkeys-lru
2.3 内存碎片
bash
# 查看碎片率
redis-cli info memory | grep mem_fragmentation_ratio
# mem_fragmentation_ratio: 1.52
# 大于1.5说明碎片较多
解决方案:
bash
# Redis 4.0+ 支持在线碎片整理
redis-cli config set activedefrag yes
# 或者重启Redis
三、主从问题
3.1 主从不同步
现象:从库数据和主库不一致
bash
# 查看复制状态
redis-cli info replication
# 主库显示
role:master
connected_slaves:1
slave0:ip=192.168.1.2,port=6379,state=online,offset=123456,lag=0
# 从库显示
role:slave
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
关键指标:
master_link_status:up正常,down断开master_last_io_seconds_ago:与主库最后通信时间lag:复制延迟
常见原因:
- 网络问题
bash
# 从库上检查
redis-cli info replication | grep master_link_down_since_seconds
- 复制缓冲区溢出
bash
# 主库配置
redis-cli config get repl-backlog-size
# 默认1MB,高并发写入需要调大
# 建议配置
repl-backlog-size 256mb
- 从库复制超时
bash
# 检查超时配置
redis-cli config get repl-timeout
# 默认60秒
# 大数据量同步可能需要调大
repl-timeout 300
3.2 主从切换后数据丢失
原因:异步复制导致主库写入未同步到从库就宕机了
解决方案:
bash
# 配置最少从库数量
min-replicas-to-write 1
min-replicas-max-lag 10
# 含义:至少1个从库延迟不超过10秒,否则主库拒绝写入
四、性能问题
4.1 慢查询
bash
# 查看慢查询日志
redis-cli slowlog get 10
# 输出示例
1) 1) (integer) 123 # ID
2) (integer) 1609459200 # 时间戳
3) (integer) 15000 # 耗时(微秒)
4) 1) "keys" # 命令
2) "*"
# 配置慢查询阈值(微秒)
redis-cli config set slowlog-log-slower-than 10000 # 10ms
redis-cli config set slowlog-max-len 1000
常见慢操作:
| 命令 | 问题 | 替代方案 |
|---|---|---|
| keys * | 全库扫描 | scan |
| hgetall | 大hash | hscan / 只取需要的字段 |
| smembers | 大set | sscan |
| lrange 0 -1 | 大list | 分页获取 |
| del bigkey | 阻塞删除 | unlink(异步删除) |
4.2 热点key
现象:QPS很高但集群负载不均
bash
# 开启热点key统计(Redis 4.0+)
redis-cli --hotkeys
# 或者用monitor采样(生产慎用)
redis-cli monitor | head -10000 > monitor.log
awk '{print $4}' monitor.log | sort | uniq -c | sort -rn | head
解决方案:
- 本地缓存:热点数据在应用层缓存
- 读写分离:读请求分散到从库
- key拆分 :
hotkey→hotkey:1,hotkey:2...
4.3 大key删除阻塞
bash
# 查看key元素数量
redis-cli llen mylist
redis-cli hlen myhash
redis-cli scard myset
# 异步删除(Redis 4.0+)
redis-cli unlink bigkey
# 或者分批删除
# Hash
redis-cli hscan myhash 0 count 100
# 然后 hdel 分批删
# List
redis-cli ltrim mylist 0 -1001 # 每次删1000个
五、持久化问题
5.1 RDB持久化失败
现象 :日志报Background saving error
bash
# 查看最近一次持久化状态
redis-cli info persistence
# rdb_last_bgsave_status: ok/err
# rdb_last_bgsave_time_sec: 5
# 查看日志
tail -100 /var/log/redis/redis-server.log
常见原因:
- 磁盘空间不足
bash
df -h
- fork失败(内存不足)
bash
# 检查overcommit配置
cat /proc/sys/vm/overcommit_memory
# 0: 默认,可能导致fork失败
# 1: 允许overcommit
# 修改
echo 1 > /proc/sys/vm/overcommit_memory
# 或永久修改 /etc/sysctl.conf
vm.overcommit_memory = 1
- 透明大页导致延迟
bash
# 禁用透明大页
echo never > /sys/kernel/mm/transparent_hugepage/enabled
5.2 AOF重写阻塞
bash
# 查看AOF状态
redis-cli info persistence | grep aof
# 手动触发重写
redis-cli bgrewriteaof
# 配置自动重写
auto-aof-rewrite-percentage 100 # 增长100%触发
auto-aof-rewrite-min-size 64mb # 最小64MB才触发
六、集群问题
6.1 集群状态异常
bash
# 查看集群状态
redis-cli cluster info
# cluster_state:ok/fail
# cluster_slots_assigned:16384
# cluster_slots_ok:16384
# cluster_slots_fail:0
# 查看节点
redis-cli cluster nodes
常见问题:
- slot未分配
bash
# 检查slot覆盖
redis-cli cluster slots
# 手动分配
redis-cli cluster addslots 0 1 2 ...
- 节点故障
bash
# 查看失败节点
redis-cli cluster nodes | grep fail
# 手动故障转移
redis-cli cluster failover
6.2 MOVED/ASK错误
客户端报MOVED或ASK错误,说明请求到了错误的节点。
解决:使用集群模式的客户端
bash
# 命令行用-c参数
redis-cli -c -h host -p port
# 客户端库要用cluster模式
# Java: JedisCluster
# Python: redis-py-cluster
6.3 跨机房/跨网络访问
多个机房部署的Redis需要互通,或者本地开发需要连远程Redis。
方案1:SSH隧道
bash
ssh -L 6379:redis-server:6379 user@跳板机 -N
redis-cli -h 127.0.0.1
方案2:VPN/组网
如果经常需要访问多个内网Redis,用组网工具更方便。WireGuard、ZeroTier、星空组网这类工具配置一次,后续直接用内网IP访问,不用每次建隧道。
七、快速诊断脚本
bash
#!/bin/bash
# redis_check.sh
REDIS_CLI="redis-cli"
HOST=${1:-127.0.0.1}
PORT=${2:-6379}
echo "=== Redis诊断 $HOST:$PORT ==="
echo -e "\n[1] 连通性"
$REDIS_CLI -h $HOST -p $PORT ping
echo -e "\n[2] 内存使用"
$REDIS_CLI -h $HOST -p $PORT info memory | grep -E "used_memory_human|maxmemory_human|mem_fragmentation_ratio"
echo -e "\n[3] 连接数"
$REDIS_CLI -h $HOST -p $PORT info clients | grep connected_clients
echo -e "\n[4] 复制状态"
$REDIS_CLI -h $HOST -p $PORT info replication | grep -E "role|master_link_status|connected_slaves"
echo -e "\n[5] 持久化"
$REDIS_CLI -h $HOST -p $PORT info persistence | grep -E "rdb_last_bgsave_status|aof_enabled"
echo -e "\n[6] 慢查询(最近5条)"
$REDIS_CLI -h $HOST -p $PORT slowlog get 5
echo -e "\n[7] Key数量"
$REDIS_CLI -h $HOST -p $PORT dbsize
echo -e "\n[8] QPS"
$REDIS_CLI -h $HOST -p $PORT info stats | grep instantaneous_ops_per_sec
echo -e "\n=== 诊断完成 ==="
总结
Redis问题排查思路:
| 问题类型 | 排查命令 | 关键指标 |
|---|---|---|
| 连接问题 | info clients | connected_clients |
| 内存问题 | info memory | used_memory, fragmentation |
| 主从问题 | info replication | master_link_status, lag |
| 性能问题 | slowlog get | 慢查询命令 |
| 持久化 | info persistence | rdb/aof状态 |
| 集群问题 | cluster info | cluster_state |
核心命令:
bash
redis-cli info # 整体状态
redis-cli info memory # 内存
redis-cli info clients # 连接
redis-cli info replication # 主从
redis-cli slowlog get 10 # 慢查询
redis-cli --bigkeys # 大key分析
redis-cli monitor # 实时命令监控(慎用)
遇到问题先看info,90%的问题都能从这里找到线索。
有问题评论区交流。