Redis之缓存雪崩

一、缓存雪崩

缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从而形成一系列连锁反应,造成整个系统崩溃。

二、示意图

缓存正常从Redis中获取,示意图如下:

在这里插入图片描述

缓存失效瞬间示意图如下:

在这里插入图片描述

三、解决方案

以下列举两种方案,不仅限于此两种

方案一

用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上

加锁排队只是为了减轻数据库的压力,并没有提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,这是过来1000个请求999个都在阻塞的。同样会导致用户等待超时,这是个治标不治本的方法!

注意:加锁排队的解决方式分布式环境的并发问题,有可能还要解决分布式锁的问题;线程还会被阻塞,用户体验很差!因此,在真正的高并发场景下很少使用!

方案二

在原有的缓存失效时间上加一个随机说,比如随机城市1-10分钟内的随机数,这样的操作很简单,相比第一种更轻!

三、压力测试

这里是对方案二的测试,方案一没事测试,

压测前提

在3s内压1000个并发,缓存失效时间为2s
在这里插入图片描述

代码示例

伪代码,没有实际意义,只是为了测试;
get方法进行了加时处理
get3方法没有加时处理

   @GetMapping(value = "get")
    public Object get(@RequestParam(value = "key") String key){
        Object obj = redisUtil.get(key);
        if(obj ==null){
            System.out.println("这里进行数据库查询----get");
            obj = "Java有货";
            redisUtil.set(key,obj, (long) (2+Math.random()* 10));
        }
        return obj;
    }

    @GetMapping(value = "get3")
    public Object get3(@RequestParam(value = "key") String key){
        Object obj = redisUtil.get(key);
        if(obj ==null){
            System.out.println("这里进行数据库查询---- get3");
            obj = "Java有货";
            redisUtil.set(key,obj, 2);
        }
        return obj;
    }

访问情况

在这里插入图片描述

与数据库连接测试

从下图可以看出,在相同的压力环境下,进行随机时间处理,很大程度减少了开销!
在这里插入图片描述
总结:
以上只是一个接口的压测,如果整个系统所有接口用到缓存的地方设置的时间都是一样的,出现大面积失效,之后的所有请求都击中在DB上,可想而知,我们的服务会出现什么的状况!

关注 Java有货领取更多资料

联系小编。微信:372787553,带您进群互相学习
左侧小编微信,右侧获取免费资料
在这里插入图片描述

Redis缓存雪崩是指在缓存大量的缓存数据同时失效或在同一时间段内过期,导致大量的请求直接访问后端数据库,使得数据库压力骤增,甚至导致数据库宕机,从而引发系统性能下降或整个系统崩溃的现象。 造成Redis缓存雪崩的原因主要有以下几个: 1. 缓存数据同时过期:如果大量的缓存数据同时过期,那么在缓存数据重新生成之前,所有的请求都会直接访问数据库。这会导致数据库瞬间承受大量的请求,造成数据库负载激增。 2. 缓存层故障:当缓存层发生故障,无法提供正常的缓存服务时,所有的请求都会直接访问后端数据库。如果数据库无法承受如此大量的请求,就会导致数据库性能下降或宕机。 3. 缓存集失效:如果所有的缓存数据都集在同一个时间点失效,那么在缓存数据重新生成之前,所有的请求都会直接访问数据库。这样会造成数据库瞬间承受巨大的压力。 针对Redis缓存雪崩问题,可以采取以下几种解决方法: 1. 设置缓存失效时间的随机性:可以在设置缓存失效时间时,给每个缓存数据都加上一个随机的失效时间,使得缓存数据在不同的时间失效,避免同时失效。 2. 引入缓存预热机制:在系统启动或低峰期,可以提前主动加载缓存数据,使得缓存数据在使用时已经被加载到缓存,避免在高峰期大量请求同时访问数据库。 3. 限流和熔断:可以通过限制请求的并发数或设置熔断策略来控制对数据库的访问压力,避免数据库承受过多的请求导致崩溃。 4. 多级缓存:可以引入多级缓存架构,将缓存数据分为多个层级,例如本地缓存、分布式缓存和数据库,使得请求在不同层级的缓存逐级查找,减轻单一缓存层的压力。 相关问题: 1. 除了Redis,还有哪些常用的缓存系统? 2. 如何设计一个高可用的缓存架构? 3. 缓存穿透和缓存击穿是什么,它们与缓存雪崩有何区别? 4. 如何监控和预防缓存雪崩问题的发生?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小杨同学~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值