前言
Redis用着用着总会遇到各种问题:连接超时、内存暴涨、主从不同步、缓存雪崩…
这篇整理Redis常见问题的排查思路和解决方案,线上出问题时能快速定位。
一、连接问题
1.1 连接超时
现象:客户端报Connection timed out或JedisConnectionException
排查步骤:
# 1. 检查Redis是否存活redis-cliping# 2. 检查端口是否监听ss-tlnp|grep6379# 3. 检查连接数redis-cli info clients# connected_clients:150 ← 当前连接数# 4. 查看最大连接数配置redis-cli config get maxclients# maxclients: 10000# 5. 检查是否有慢查询阻塞redis-cli slowlog get10常见原因:
- 连接数打满
# 查看客户端列表redis-cli client list# 找到空闲时间长的连接redis-cli client list|awk-F'[ =]''{print $4, $10}'|sort-k2-rn|head解决:增大maxclients,或检查客户端连接池配置。
- 网络问题
# 测试网络延迟redis-cli--latency# 持续监控redis-cli --latency-history- Redis阻塞
# 检查阻塞操作redis-cli info stats|grepblocked1.2 连接被拒绝
现象:Connection refused
# 检查绑定地址redis-cli config getbind# 如果是 127.0.0.1,远程无法连接# 修改配置# /etc/redis/redis.confbind0.0.0.0# 或具体IP# 检查防火墙iptables-L-n|grep6379firewall-cmd --list-ports|grep6379二、内存问题
2.1 内存暴涨
排查步骤:
# 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. 分析大keyredis-cli--bigkeys# 4. 扫描特定前缀的key数量redis-cli keys"user:*"|wc-l# 注意:生产环境用 scan 代替 keysredis-cli scan0match"user:*"count1000找出大key:
# 分析RDB文件(推荐)# 安装 rdb-toolspipinstallrdbtools python-lzf# 导出大key报告rdb-cmemory /var/lib/redis/dump.rdb--bytes10240-fmemory.csv或者用Redis自带命令:
# 查看某个key的内存占用redis-cli memory usage mykey# 批量分析redis-cli--bigkeys-i0.1# 每100ms扫描一次,降低影响2.2 内存淘汰
现象:写入失败,报OOM command not allowed
# 查看淘汰策略redis-cli config get maxmemory-policy# volatile-lru / allkeys-lru / noeviction 等# 查看淘汰统计redis-cli info stats|grepevicted# evicted_keys: 12345淘汰策略说明:
| 策略 | 说明 |
|---|---|
| noeviction | 不淘汰,内存满了报错 |
| volatile-lru | 淘汰有过期时间的key(LRU) |
| allkeys-lru | 淘汰所有key(LRU) |
| volatile-ttl | 淘汰TTL最短的key |
| volatile-random | 随机淘汰有过期时间的key |
| allkeys-random | 随机淘汰 |
建议配置:
# redis.confmaxmemory 4gb maxmemory-policy allkeys-lru2.3 内存碎片
# 查看碎片率redis-cli info memory|grepmem_fragmentation_ratio# mem_fragmentation_ratio: 1.52# 大于1.5说明碎片较多解决方案:
# Redis 4.0+ 支持在线碎片整理redis-cli configsetactivedefragyes# 或者重启Redis三、主从问题
3.1 主从不同步
现象:从库数据和主库不一致
# 查看复制状态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:复制延迟
常见原因:
- 网络问题
# 从库上检查redis-cli info replication|grepmaster_link_down_since_seconds- 复制缓冲区溢出
# 主库配置redis-cli config get repl-backlog-size# 默认1MB,高并发写入需要调大# 建议配置repl-backlog-size 256mb- 从库复制超时
# 检查超时配置redis-cli config get repl-timeout# 默认60秒# 大数据量同步可能需要调大repl-timeout3003.2 主从切换后数据丢失
原因:异步复制导致主库写入未同步到从库就宕机了
解决方案:
# 配置最少从库数量min-replicas-to-write1min-replicas-max-lag10# 含义:至少1个从库延迟不超过10秒,否则主库拒绝写入四、性能问题
4.1 慢查询
# 查看慢查询日志redis-cli slowlog get10# 输出示例1)1)(integer)123# ID2)(integer)1609459200# 时间戳3)(integer)15000# 耗时(微秒)4)1)"keys"# 命令2)"*"# 配置慢查询阈值(微秒)redis-cli configsetslowlog-log-slower-than10000# 10msredis-cli configsetslowlog-max-len1000常见慢操作:
| 命令 | 问题 | 替代方案 |
|---|---|---|
| keys * | 全库扫描 | scan |
| hgetall | 大hash | hscan / 只取需要的字段 |
| smembers | 大set | sscan |
| lrange 0 -1 | 大list | 分页获取 |
| del bigkey | 阻塞删除 | unlink(异步删除) |
4.2 热点key
现象:QPS很高但集群负载不均
# 开启热点key统计(Redis 4.0+)redis-cli--hotkeys# 或者用monitor采样(生产慎用)redis-cli monitor|head-10000>monitor.logawk'{print $4}'monitor.log|sort|uniq-c|sort-rn|head解决方案:
- 本地缓存:热点数据在应用层缓存
- 读写分离:读请求分散到从库
- key拆分:
hotkey→hotkey:1,hotkey:2…
4.3 大key删除阻塞
# 查看key元素数量redis-cli llen mylist redis-cli hlen myhash redis-cli scard myset# 异步删除(Redis 4.0+)redis-cli unlink bigkey# 或者分批删除# Hashredis-cli hscan myhash0count100# 然后 hdel 分批删# Listredis-cli ltrim mylist0-1001# 每次删1000个五、持久化问题
5.1 RDB持久化失败
现象:日志报Background saving error
# 查看最近一次持久化状态redis-cli info persistence# rdb_last_bgsave_status: ok/err# rdb_last_bgsave_time_sec: 5# 查看日志tail-100/var/log/redis/redis-server.log常见原因:
- 磁盘空间不足
df-h- fork失败(内存不足)
# 检查overcommit配置cat/proc/sys/vm/overcommit_memory# 0: 默认,可能导致fork失败# 1: 允许overcommit# 修改echo1>/proc/sys/vm/overcommit_memory# 或永久修改 /etc/sysctl.confvm.overcommit_memory=1- 透明大页导致延迟
# 禁用透明大页echonever>/sys/kernel/mm/transparent_hugepage/enabled5.2 AOF重写阻塞
# 查看AOF状态redis-cli info persistence|grepaof# 手动触发重写redis-cli bgrewriteaof# 配置自动重写auto-aof-rewrite-percentage100# 增长100%触发auto-aof-rewrite-min-size 64mb# 最小64MB才触发六、集群问题
6.1 集群状态异常
# 查看集群状态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未分配
# 检查slot覆盖redis-cli cluster slots# 手动分配redis-cli cluster addslots012...- 节点故障
# 查看失败节点redis-cli cluster nodes|grepfail# 手动故障转移redis-cli cluster failover6.2 MOVED/ASK错误
客户端报MOVED或ASK错误,说明请求到了错误的节点。
解决:使用集群模式的客户端
# 命令行用-c参数redis-cli-c-hhost-pport# 客户端库要用cluster模式# Java: JedisCluster# Python: redis-py-cluster七、快速诊断脚本
#!/bin/bash# redis_check.shREDIS_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$PORTpingecho-e"\n[2] 内存使用"$REDIS_CLI-h$HOST-p$PORTinfo memory|grep-E"used_memory_human|maxmemory_human|mem_fragmentation_ratio"echo-e"\n[3] 连接数"$REDIS_CLI-h$HOST-p$PORTinfo clients|grepconnected_clientsecho-e"\n[4] 复制状态"$REDIS_CLI-h$HOST-p$PORTinfo replication|grep-E"role|master_link_status|connected_slaves"echo-e"\n[5] 持久化"$REDIS_CLI-h$HOST-p$PORTinfo persistence|grep-E"rdb_last_bgsave_status|aof_enabled"echo-e"\n[6] 慢查询(最近5条)"$REDIS_CLI-h$HOST-p$PORTslowlog get5echo-e"\n[7] Key数量"$REDIS_CLI-h$HOST-p$PORTdbsizeecho-e"\n[8] QPS"$REDIS_CLI-h$HOST-p$PORTinfo stats|grepinstantaneous_ops_per_sececho-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 |
核心命令:
redis-cli info# 整体状态redis-cli info memory# 内存redis-cli info clients# 连接redis-cli info replication# 主从redis-cli slowlog get10# 慢查询redis-cli--bigkeys# 大key分析redis-cli monitor# 实时命令监控(慎用)遇到问题先看info,90%的问题都能从这里找到线索。
有问题评论区交流。