0
0
0

缓存雪崩及解决方案

2023-02-27
2026-10-24
文章摘要
|

一、什么是缓存雪崩?

缓存雪崩(Cache Avalanche) 是指大量缓存 Key 在同一时间失效,或者 Redis 服务发生故障,导致大量请求无法命中缓存,集中访问 MySQL,造成数据库压力激增,甚至导致系统崩溃。

主要有两种场景:

1. 大量 Key 同时过期

大量缓存 Key 同时过期
        ↓
Redis 缓存未命中
        ↓
大量请求访问 MySQL
        ↓
数据库压力激增

2. Redis 服务宕机

Redis 服务不可用
        ↓
缓存查询失败
        ↓
大量请求回源 MySQL
        ↓
数据库压力激增

注意:大量 Key 同时过期并不意味着 Redis 宕机;Redis 宕机后也不一定会直接访问 MySQL,具体取决于系统的降级和异常处理策略。

二、解决方案

1. 设置随机 TTL

避免大量 Key 在同一时间过期,可以在基础 TTL 上增加随机时间。

例如,原本所有 Key 都设置 30 分钟过期:

redisTemplate.opsForValue()
    .set(key, value, 30, TimeUnit.MINUTES);

优化后:

// 基础30分钟,随机增加0~10分钟
int ttl = 30 + ThreadLocalRandom.current().nextInt(11);

redisTemplate.opsForValue()
    .set(key, value, ttl, TimeUnit.MINUTES);

这样不同 Key 的过期时间就会分散,降低缓存同时失效的风险。

适用场景:大量 Key 同时过期。

2. Redis 高可用

通过 Redis Sentinel(哨兵)或 Redis Cluster(集群)实现高可用。

例如:

Redis 主节点 A
      ↓ 主从复制
Redis 从节点 B

主节点 A 宕机
      ↓
故障自动转移
      ↓
从节点 B 晋升为主节点
      ↓
恢复缓存服务

注意:

  • 主从复制用于数据同步,故障转移依赖 Sentinel 或 Cluster 等机制。

  • 故障切换需要一定时间,并非完全无感。

  • Redis 高可用不能完全替代限流和降级措施。

适用场景:Redis 节点故障或服务不可用。

3. 限流、降级和熔断

当 Redis 出现异常或数据库压力过大时,需要保护后端系统。

① 限流

限制请求数量,例如每秒最多处理 1000 个请求,超过限制的请求直接拒绝或排队。

常见实现:Redis + Lua、Sentinel(阿里巴巴开源的流量治理组件)、Spring Cloud Gateway。

② 降级

暂时关闭非核心功能,或者返回默认数据、兜底结果。

例如:商品推荐服务异常时,暂时返回默认推荐列表,而不是继续大量查询 MySQL。

③ 熔断

当 Redis 或下游服务持续异常时,暂时停止访问故障服务,避免大量请求反复失败。

需要注意:

  • 限流:控制请求数量。

  • 降级:降低功能或服务质量。

  • 熔断:暂时停止对异常依赖的调用。

适用场景:缓存服务故障或数据库访问压力过大。

4. 多级缓存

通过多层缓存降低对 Redis 和 MySQL 的依赖。

例如:

客户端请求
     ↓
浏览器缓存
     ↓ 未命中
Nginx 缓存
     ↓ 未命中
JVM 本地缓存(Caffeine)
     ↓ 未命中
Redis 分布式缓存
     ↓ 未命中
MySQL 数据库

常见缓存层:

缓存层

主要作用

浏览器缓存

减少重复网络请求

Nginx 缓存

缓存静态资源或合适的 HTTP 响应

JVM 本地缓存

减少 Redis 访问

Redis 缓存

减少 MySQL 访问

注意:

  • 多级缓存需要考虑数据一致性。

  • 不同业务不一定需要所有缓存层。

  • JVM 本地缓存常见实现是 Caffeine,属于第三方依赖,不是 Java 8 自带的。

  • 各层缓存应根据数据特点设计,避免所有缓存同时过期。

适用场景:高并发读取、热点数据访问。

三、其他优化方案

1. 缓存预热

系统启动或活动开始之前,提前将热点数据加载到 Redis。

这样可以避免大量请求同时查询 MySQL。

2. 互斥锁重建缓存

缓存失效时,通过互斥锁控制只有一个线程查询数据库并重建缓存,避免同一个 Key 被大量并发请求重复查询。

该方案主要用于解决缓存击穿,也能缓解雪崩过程中单个 Key 的并发重建问题。

但对于大量不同 Key 同时失效,仍需要结合随机 TTL、限流等方案。

四、缓存穿透、击穿、雪崩的区别

问题

原因

解决方案

缓存穿透

查询的数据在 Redis 和数据库中都不存在

缓存空值、布隆过滤器

缓存击穿

某个热点 Key 失效,大量请求访问数据库

互斥锁、逻辑过期

缓存雪崩

大量 Key 同时失效或 Redis 服务故障

随机 TTL、高可用、限流降级、多级缓存

五、面试总结

Redis 缓存雪崩是指大量缓存 Key 同时失效,或者 Redis 服务不可用,导致大量请求集中访问数据库,造成数据库压力激增。

常见解决方案有:

  1. 随机 TTL:给不同 Key 设置不同的过期时间,避免集中失效。

  2. Redis 高可用:通过 Sentinel 或 Cluster 实现故障转移,降低单节点故障的影响。

  3. 限流、降级、熔断:限制请求数量,暂时关闭非核心服务,避免故障扩大。

  4. 多级缓存:使用浏览器、Nginx、JVM 本地缓存及 Redis,分散缓存访问压力。

  5. 缓存预热:提前加载热点数据,避免集中回源数据库。

实际生产中,通常需要根据业务特点组合使用多种方案。

核心记忆:

  • 随机 TTL:防止缓存同时过期。

  • Redis 高可用:减少 Redis 故障影响。

  • 限流降级:保护数据库和核心业务。

  • 多级缓存:分散访问压力。

  • 缓存预热:提前准备热点数据。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或者给予支持!

评论