Skip to content

缓存雪崩

大量缓存在同一时间失效,导致大量请求同时访问数据库,从而造成数据库压力过大甚至宕机。

TIP

Redis宕机也属于雪崩

栗子

假设有 Redis:

user:1
user:2
user:3
goods:1001
goods:1002
shop:001
config:system

平时命中率 95%,数据库压力很小。

在设定中数据的过期时间是 30分钟,在系统启动时同时进行了缓存。

例如:12:00 进行缓存,那么数据将在 12:30 过期。

此时有 50000 个请求同时到达,由于缓存已经过期,这些请求全都打到了数据库上,数据库瞬间被压垮。

这就是

缓存雪崩

缓存穿透 / 击穿 / 雪崩 的区别

问题Key数量数据是否存在
缓存穿透很多不存在的Key不存在
缓存击穿一个热点Key存在
缓存雪崩大量Key存在

解决方案

方案1:随机过期时间(最常用)

不要设定成同一的过期时间,当在同一时间缓存时很容易造成缓存雪崩。

而是通过 固定时间 + 随机数 的方式设置过期时间。

例如

java
// 30分钟 + 随机数

int ttl = 30 + Random.nextInt(10);

redis.set(key, value, ttl, TimeUnit.MINUTES);

方案2:热点数据永不过期

适用于:

  • 系统配置
  • 店铺信息
  • 省市数据
  • 菜单数据

这些很长时间都不会发生变化的数据,完全可以设置成 永久缓存

修改时删除缓存,等待下载重新加载即可。

方案3:多级缓存

浏览器缓存

Nginx缓存

Redis

MySQL

不把鸡蛋放在同一个篮子里,即使 Redis 挂掉,前面还有其他缓存,大型网站经常这样做。

方案4:限流降级

数据库压力过大:

比如有 1000000 个请求进入,只接受其中 1000 个请求,其余的返回错误信息。

json
{
    "msg":"系统繁忙,请稍后重试"
}

常见组件:

  • Sentinel
  • Gateway 限流