Redis 线上高频问题
核心概念 Redis 线上高频问题涵盖缓存穿透、击穿、雪崩、大 Key、热 Key、内存暴涨、慢查询、主从延迟等排查与解决方案。
覆盖:CPU高、内存溢出、主从同步故障、慢查询、连接打满、持久化阻塞、集群槽位异常、缓存雪崩/穿透/击穿、OOM、超时卡顿。
1. CPU 100% 高占用排查
1.1. 两大核心诱因
1.1.1. (1)主线程阻塞(单线程模型,最常见)
Redis 命令处理、RDB/AOF刷盘、主从全量同步、大key删除、大量keys/*scan阻塞主线程。
排查步骤:
- 查看慢查询
slowlog get 100,看是否存在KEYS *、HGETALL、超大集合遍历、大DEL; - 观察持久化阻塞:
# 查看持久化耗时、fork阻塞
redis-cli info persistence
latest_fork_usec数值几千上万:fork创建RDB子进程阻塞主线程;
- 查看主从同步:
info replication,全量RDB同步时主线程大量写缓冲区CPU飙升; - 监控实时命令:
redis-cli monitor(线上慎用,会加重CPU)。
1.1.2. (2)子进程CPU打满
- bgsave RDB压缩大量数据;
- aof rewrite 重写整理大量AOF日志;
- 大量持久化IO消耗内核CPU。
1.2. 排查命令
# 1. 慢查询
slowlog len
slowlog get 20
# 2. 实时命令统计(redis 6+)
redis-cli info stats | grep cmd
# 3. 查看fork阻塞时间
redis-cli info persistence | grep latest_fork_usec
# 4. 看热点大key
redis-cli --bigkeys
1.3. 优化方案
- 禁用
KEYS *,改用分页SCAN/HSCAN/ZSCAN; - 超大Hash/Set拆分,避免一次性全量读取;
- 大key异步删除:
UNLINK替代DEL; - 错开RDB/AOF rewrite业务高峰;
- 机器调高内存overcommit,减少fork阻塞;
- 读写分离,查询分流从库。
2. 内存相关问题(OOM、内存持续上涨、内存溢出、swap飙升)
2.1. 内存持续只涨不释放
原因:
- 大量过期key未主动淘汰,惰性删除;
- 大key堆积,过期后内存不会立刻释放;
- 持久化缓冲区、repl_backlog复制缓冲区占用;
- 客户端输出缓冲区溢出(主从同步、大量查询打满缓冲区)。
排查:
# 内存整体状态
info memory
# 各db key数量
info keyspace
# 扫描大key
redis-cli --bigkeys
# 查看客户端缓冲区
client list | grep -o 'output-buf=[0-9]*'
2.2. OOM Killer 杀死 Redis
触发条件:maxmemory 未配置,占用整机内存,系统OOM优先杀掉redis。
解决方案:
# redis.conf 强制限制内存
maxmemory 60gb
# 缓存场景淘汰策略
maxmemory-policy volatile-lru
2.3. swap 大量使用(si 数值飙升,性能暴跌)
内核频繁把redis内存交换到磁盘,读写延迟几十ms~秒级。
根因:内存不足、maxmemory设置过大、多进程抢占内存。
优化:
# 内核调小swap使用倾向
echo vm.swappiness=0 >> /etc/sysctl.conf
sysctl -p
# redis合理设置maxmemory,预留系统内存
2.4. 淘汰策略踩坑
allkeys-lru:所有key不分过期时间淘汰;volatile-lru(缓存推荐):只淘汰带过期的key;noeviction:内存满直接拒绝写入,业务报错,线上严禁使用。
3. 主从同步故障(频繁全量同步、同步延迟、断开、数据不一致)
3.1. 频繁触发全量RDB同步
排查:
info replication
# 对比 master_repl_offset、slave_repl_offset
诱因:
repl-backlog-size缓冲区过小,断开后offset超出环形缓冲区;- 网络抖动,从库频繁断线重连;
- 主重启生成新replid,从库无法增量同步;
- 从库client-output-buffer溢出,主主动断开连接。
优化:
# 调大复制缓冲区
repl-backlog-size 128mb
# 调大从库输出缓冲区
client-output-buffer-limit slave 256mb 64mb 60
3.2. 主从同步延迟高
- 主写入QPS极高,单从追赶不上;
- 从库磁盘性能差,回放AOF/RDB慢;
- 链式复制层级过多;
- 从库CPU弱,大量命令回放阻塞。
定位:对比主从 repl_offset 差值持续拉大。
3.3. 主从数据不一致
- 人为在从库执行写命令(关闭replica-read-only);
- 主AOF/RDB持久化失败,重启丢失数据;
- 网络丢包导致同步命令截断;
- 低版本Redis同步BUG。
3.4. 主从自动断开
防火墙6379拦截、输出缓冲区溢出、TCP超时、内存OOM杀进程。
4. 大量连接异常(连接数打满、大量TIME_WAIT、客户端超时)
4.1. 连接数超限报错 Too many connections
排查:
# 当前客户端连接
info clients
client list
原因:
- 客户端连接未复用,短连接频繁创建;
- 连接池配置过小,并发打满;
- 未设置超时,闲置连接永久占用。
优化:
# 闲置连接自动释放300s
timeout 300
# 调高最大连接
maxclients 100000
业务侧:使用连接池,避免每次新建连接。
4.2. 大量 TIME_WAIT 端口耗尽
短连接高并发,内核端口回收慢。
内核调优:
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
4.3. 客户端读取超时
现象:业务大量 read timeout。
诱因:
- 主线程阻塞(大key、持久化、全量同步);
- 主从同步占用大量带宽;
- 网络延迟高、丢包。
5. 持久化阻塞(业务写入卡顿、延迟飙升)
5.1. RDB bgsave fork 阻塞主线程
fork创建子进程时拷贝页表,内存越大阻塞越久,latest_fork_usec 上万微秒。
优化:
- 避开业务高峰执行bgsave;
- 机器开启内存大页关闭、调整overcommit_memory=1;
- 改用AOF为主,降低RDB频率。
5.2. AOF rewrite 重写阻塞
大量过期数据,AOF文件持续膨胀,rewrite大量IO、CPU消耗。
参数调优:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 折中刷盘策略 everysec
appendfsync everysec
no-appendfsync-on-rewrite yes
5.3. AOF 刷盘阻塞主线程
appendfsync always每条写强制刷盘,性能极差;everysec每秒后台刷盘,推荐生产;no交给系统刷盘,宕机丢失最多30秒数据。
6. Redis Cluster 分片集群专属故障
6.1. 集群状态 fail 不可用
排查:
redis-cli -c --cluster check ip:6379
cluster info
cluster nodes
诱因:
- 某分片主库宕机,无可用从库未完成切换;
- 槽位未全部分配(slot 0-16383缺失);
- 节点之间端口不通(集群总线16379)。
6.2. MOVED / ASK 重定向报错
- MOVED:key所属槽永久迁移到其他主节点,客户端未缓存路由;
- ASK:槽正在迁移中,临时跳转;
业务解决:客户端开启集群模式-c,自动跳转。
6.3. 槽迁移卡顿、业务超时
rebalance迁移slot期间,对应key读写阻塞,低峰期执行迁移。
6.4. 分片主从切换失败
从库复制偏移量落后太多、网络不通、从库优先级过低,集群不提升从库为主。
7. 三大缓存经典问题:雪崩、穿透、击穿
7.1. 缓存雪崩
大量key同时过期,大量请求打透到DB,数据库崩溃。
解决方案:
- 过期时间增加随机偏移量;
- 多级缓存、限流、熔断;
- 永不过期热点key。
7.2. 缓存穿透
查询不存在key,绕过缓存直达DB(如id=-1、非法参数)。
解决方案:
- 空值缓存短期过期;
- 布隆过滤器拦截不存在key;
- 接口参数校验。
7.3. 缓存击穿
热点单一key过期,瞬间海量请求打数据库。
解决方案:
- 热点key永不过期;
- 分布式互斥锁互斥更新;
- 逻辑过期,后台异步刷新。
8. 慢查询 & 业务超时通用排查流程
标准排查步骤(线上通用):
- 查看慢日志
slowlog get,定位慢命令; - 查看CPU、内存、swap指标,判断主线程是否阻塞;
- 查看持久化info,确认fork/rewrite是否阻塞;
- 主从场景查看同步延迟、repl_backlog;
- 查看客户端连接数、输出缓冲区是否溢出;
- 集群环境检查slot分配、节点状态;
- 网络层查看丢包、延迟、端口占用。
9. 常用排查命令汇总
# 基础全局状态
info server
info clients
info memory
info persistence
info replication
info stats
# 慢查询
slowlog len
slowlog get 50
# 大key扫描
redis-cli --bigkeys -h x.x.x.x -p 6379
# 集群检查
redis-cli --cluster check ip:6379
cluster info
cluster nodes
# 实时客户端
client list
client kill ip:port
# 监控流量(慎用,高并发加重负载)
redis-cli monitor
10. 线上通用稳定优化总结
- 禁止KEYS、HGETALL,使用SCAN系列分页;大key用UNLINK;
- 合理maxmemory+淘汰策略,关闭swap,预留系统内存;
- AOF everysec,错开RDB/rewrite业务高峰;
- 调大repl-backlog与slave输出缓冲区,减少全量同步;
- 读写分离,查询压力下放从库;
- 集群业务使用哈希标签,避免跨槽批量操作报错;
- 客户端使用连接池,设置闲置连接超时;
- 热点key打散、过期时间随机偏移,防雪崩击穿穿透;
- 监控核心指标:CPU、内存、swap、复制偏移、慢查询数量、连接数、fork阻塞耗时。完整排查手册
覆盖:CPU高、内存溢出、主从同步故障、慢查询、连接打满、持久化阻塞、集群槽位异常、缓存雪崩/穿透/击穿、OOM、超时卡顿。
11. CPU 100% 高占用排查
11.1. 两大核心诱因
11.1.1. (1)主线程阻塞(单线程模型,最常见)
Redis 命令处理、RDB/AOF刷盘、主从全量同步、大key删除、大量keys/*scan阻塞主线程。
排查步骤:
- 查看慢查询
slowlog get 100,看是否存在KEYS *、HGETALL、超大集合遍历、大DEL; - 观察持久化阻塞:
# 查看持久化耗时、fork阻塞
redis-cli info persistence
latest_fork_usec数值几千上万:fork创建RDB子进程阻塞主线程;
- 查看主从同步:
info replication,全量RDB同步时主线程大量写缓冲区CPU飙升; - 监控实时命令:
redis-cli monitor(线上慎用,会加重CPU)。
11.1.2. (2)子进程CPU打满
- bgsave RDB压缩大量数据;
- aof rewrite 重写整理大量AOF日志;
- 大量持久化IO消耗内核CPU。
11.2. 排查命令
# 1. 慢查询
slowlog len
slowlog get 20
# 2. 实时命令统计(redis 6+)
redis-cli info stats | grep cmd
# 3. 查看fork阻塞时间
redis-cli info persistence | grep latest_fork_usec
# 4. 看热点大key
redis-cli --bigkeys
11.3. 优化方案
- 禁用
KEYS *,改用分页SCAN/HSCAN/ZSCAN; - 超大Hash/Set拆分,避免一次性全量读取;
- 大key异步删除:
UNLINK替代DEL; - 错开RDB/AOF rewrite业务高峰;
- 机器调高内存overcommit,减少fork阻塞;
- 读写分离,查询分流从库。
12. 内存相关问题(OOM、内存持续上涨、内存溢出、swap飙升)
12.1. 内存持续只涨不释放
原因:
- 大量过期key未主动淘汰,惰性删除;
- 大key堆积,过期后内存不会立刻释放;
- 持久化缓冲区、repl_backlog复制缓冲区占用;
- 客户端输出缓冲区溢出(主从同步、大量查询打满缓冲区)。
排查:
# 内存整体状态
info memory
# 各db key数量
info keyspace
# 扫描大key
redis-cli --bigkeys
# 查看客户端缓冲区
client list | grep -o 'output-buf=[0-9]*'
12.2. OOM Killer 杀死 Redis
触发条件:maxmemory 未配置,占用整机内存,系统OOM优先杀掉redis。
解决方案:
# redis.conf 强制限制内存
maxmemory 60gb
# 缓存场景淘汰策略
maxmemory-policy volatile-lru
12.3. swap 大量使用(si 数值飙升,性能暴跌)
内核频繁把redis内存交换到磁盘,读写延迟几十ms~秒级。
根因:内存不足、maxmemory设置过大、多进程抢占内存。
优化:
# 内核调小swap使用倾向
echo vm.swappiness=0 >> /etc/sysctl.conf
sysctl -p
# redis合理设置maxmemory,预留系统内存
12.4. 淘汰策略踩坑
allkeys-lru:所有key不分过期时间淘汰;volatile-lru(缓存推荐):只淘汰带过期的key;noeviction:内存满直接拒绝写入,业务报错,线上严禁使用。
13. 主从同步故障(频繁全量同步、同步延迟、断开、数据不一致)
13.1. 频繁触发全量RDB同步
排查:
info replication
# 对比 master_repl_offset、slave_repl_offset
诱因:
repl-backlog-size缓冲区过小,断开后offset超出环形缓冲区;- 网络抖动,从库频繁断线重连;
- 主重启生成新replid,从库无法增量同步;
- 从库client-output-buffer溢出,主主动断开连接。
优化:
# 调大复制缓冲区
repl-backlog-size 128mb
# 调大从库输出缓冲区
client-output-buffer-limit slave 256mb 64mb 60
13.2. 主从同步延迟高
- 主写入QPS极高,单从追赶不上;
- 从库磁盘性能差,回放AOF/RDB慢;
- 链式复制层级过多;
- 从库CPU弱,大量命令回放阻塞。
定位:对比主从 repl_offset 差值持续拉大。
13.3. 主从数据不一致
- 人为在从库执行写命令(关闭replica-read-only);
- 主AOF/RDB持久化失败,重启丢失数据;
- 网络丢包导致同步命令截断;
- 低版本Redis同步BUG。
13.4. 主从自动断开
防火墙6379拦截、输出缓冲区溢出、TCP超时、内存OOM杀进程。
14. 大量连接异常(连接数打满、大量TIME_WAIT、客户端超时)
14.1. 连接数超限报错 Too many connections
排查:
# 当前客户端连接
info clients
client list
原因:
- 客户端连接未复用,短连接频繁创建;
- 连接池配置过小,并发打满;
- 未设置超时,闲置连接永久占用。
优化:
# 闲置连接自动释放300s
timeout 300
# 调高最大连接
maxclients 100000
业务侧:使用连接池,避免每次新建连接。
14.2. 大量 TIME_WAIT 端口耗尽
短连接高并发,内核端口回收慢。
内核调优:
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 1024 65535
14.3. 客户端读取超时
现象:业务大量 read timeout。
诱因:
- 主线程阻塞(大key、持久化、全量同步);
- 主从同步占用大量带宽;
- 网络延迟高、丢包。
15. 持久化阻塞(业务写入卡顿、延迟飙升)
15.1. RDB bgsave fork 阻塞主线程
fork创建子进程时拷贝页表,内存越大阻塞越久,latest_fork_usec 上万微秒。
优化:
- 避开业务高峰执行bgsave;
- 机器开启内存大页关闭、调整overcommit_memory=1;
- 改用AOF为主,降低RDB频率。
15.2. AOF rewrite 重写阻塞
大量过期数据,AOF文件持续膨胀,rewrite大量IO、CPU消耗。
参数调优:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# 折中刷盘策略 everysec
appendfsync everysec
no-appendfsync-on-rewrite yes
15.3. AOF 刷盘阻塞主线程
appendfsync always每条写强制刷盘,性能极差;everysec每秒后台刷盘,推荐生产;no交给系统刷盘,宕机丢失最多30秒数据。
16. Redis Cluster 分片集群专属故障
16.1. 集群状态 fail 不可用
排查:
redis-cli -c --cluster check ip:6379
cluster info
cluster nodes
诱因:
- 某分片主库宕机,无可用从库未完成切换;
- 槽位未全部分配(slot 0-16383缺失);
- 节点之间端口不通(集群总线16379)。
16.2. MOVED / ASK 重定向报错
- MOVED:key所属槽永久迁移到其他主节点,客户端未缓存路由;
- ASK:槽正在迁移中,临时跳转;
业务解决:客户端开启集群模式-c,自动跳转。
16.3. 槽迁移卡顿、业务超时
rebalance迁移slot期间,对应key读写阻塞,低峰期执行迁移。
16.4. 分片主从切换失败
从库复制偏移量落后太多、网络不通、从库优先级过低,集群不提升从库为主。
17. 三大缓存经典问题:雪崩、穿透、击穿
17.1. 缓存雪崩
大量key同时过期,大量请求打透到DB,数据库崩溃。
解决方案:
- 过期时间增加随机偏移量;
- 多级缓存、限流、熔断;
- 永不过期热点key。
17.2. 缓存穿透
查询不存在key,绕过缓存直达DB(如id=-1、非法参数)。
解决方案:
- 空值缓存短期过期;
- 布隆过滤器拦截不存在key;
- 接口参数校验。
17.3. 缓存击穿
热点单一key过期,瞬间海量请求打数据库。
解决方案:
- 热点key永不过期;
- 分布式互斥锁互斥更新;
- 逻辑过期,后台异步刷新。
18. 慢查询 & 业务超时通用排查流程
标准排查步骤(线上通用):
- 查看慢日志
slowlog get,定位慢命令; - 查看CPU、内存、swap指标,判断主线程是否阻塞;
- 查看持久化info,确认fork/rewrite是否阻塞;
- 主从场景查看同步延迟、repl_backlog;
- 查看客户端连接数、输出缓冲区是否溢出;
- 集群环境检查slot分配、节点状态;
- 网络层查看丢包、延迟、端口占用。
19. 常用排查命令汇总
# 基础全局状态
info server
info clients
info memory
info persistence
info replication
info stats
# 慢查询
slowlog len
slowlog get 50
# 大key扫描
redis-cli --bigkeys -h x.x.x.x -p 6379
# 集群检查
redis-cli --cluster check ip:6379
cluster info
cluster nodes
# 实时客户端
client list
client kill ip:port
# 监控流量(慎用,高并发加重负载)
redis-cli monitor
20. 线上通用稳定优化总结
- 禁止KEYS、HGETALL,使用SCAN系列分页;大key用UNLINK;
- 合理maxmemory+淘汰策略,关闭swap,预留系统内存;
- AOF everysec,错开RDB/rewrite业务高峰;
- 调大repl-backlog与slave输出缓冲区,减少全量同步;
- 读写分离,查询压力下放从库;
- 集群业务使用哈希标签,避免跨槽批量操作报错;
- 客户端使用连接池,设置闲置连接超时;
- 热点key打散、过期时间随机偏移,防雪崩击穿穿透;
- 监控核心指标:CPU、内存、swap、复制偏移、慢查询数量、连接数、fork阻塞耗时。
关联文档