redis的缓存穿透、缓存击穿和缓存雪崩的介绍以及解决方案

 

目录

 

一、缓存穿透

1.1 什么是缓存穿透

1.2 出现的原因

1.3 如何解决

二、缓存击穿

2.1 什么是缓存击穿

2.2 出现的原因

2.3 解决方案

三、缓存雪崩

3.1什么是缓存雪崩

3.2 出现的原因

3.3解决方案 


一、缓存穿透

1.1 什么是缓存穿透

是指缓存和数据库中都没有的数据,导致请求直接打到数据库,如一些恶意请求,会让后端存储负载加大。通常可以在程序中统计总调用数、缓存层命中数,如果同一个key的缓存命中率很低,可能就是出现了缓存穿透。

1.2 出现的原因

  1. 自身业务代码或者数据的问题(如set和get的key不一致)。
  2. 一些恶意攻击、爬虫等造成大量空命中(爬取商城商品数据,超大循环递增商品的ID)。

1.3 如何解决

  1.  缓存空对象:从缓存中取不到的数据,在数据库中也没有取到,这时可以将key-value写为key-null。 缓存空对象会有两个问题:

    第一,value为null 不代表不占用内存空间,空值做了缓存,意味着缓存层中存了更多的键,需要更多的内存空间,比较有效的方法是针对这类数据设置一个较短的过期时间,让其自动剔除,如30秒(设置太长会导致正常情况也没法使用)

    第二,缓存层和存储层的数据会有一段时间窗口的不一致,可能会对业务有一定影响。例如在过期时间内,如果此时存储层添加了这个数据,那此段时间就会出现缓存层和存储层数据的不一致,此时可以利用消息系统或者其他方式清除掉缓存层中的空对象(入库的时候去同步缓存数据)。

  2. 接口层根据具体业务场景增加校验,如用户鉴权校验,id做基础校验,id<=0或者大于某个范围的直接拦截。

  3. 使用布隆过滤器拦截(布隆过滤器有待整理
方案适用场景维护成本
缓存空对象

数据命中率不高

数据频繁变化实时性高

代码维护简单

需要过多的内存空间

数据不一致问题

布隆过滤器

数据命中率不高

数据相对固定实时性低

代码维护复杂

缓存空间少

二、缓存击穿

2.1 什么是缓存击穿

是指缓存中没有但是数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读取缓存没有读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大。

2.2 出现的原因

系统中存在以下两个问题时需要引起注意:

  • 当前key是一个热点key(例如一个秒杀活动),并发量非常大。
  • 重建缓存不能在短时间完成,可能是一个复杂计算,例如复杂的SQL、多次IO、多个依赖等。

在缓存失效的瞬间,有大量线程来重建缓存,造成后端负载加大,甚至可能会让应用崩溃


2.3 解决方案

1.设置热点数据永不过期;
2.加互斥锁。

public static String getData(String key){
    //从缓存读取数据
    String result = getDataFromRedis(key);
    //缓存中不存在数据
    if(result == null ){
        //去获取锁,获取成功,去数据库取数据
        if(reenLock.tryLock())    {
            //从数据库获取数据
            result = getDataFromMysql(key);
            //更新缓存数据
            if(result != null ){
                setDataToCache(key,result);
            }
            //释放锁
            reenLock.unlock();

        }
        //获取锁失败
        else{    
            //暂停100ms再重新去获取锁
            Thread.sleep(100);
            result= getData(key);
        }

    }

    return result;

}

2种方案对比:

  • 互斥锁:这种方案思路比较简单,但是存在一定的隐患,如果在查询数据库 + 和重建缓存(key失效后进行了大量的计算)时间过长,也可能会存在死锁和线程池阻塞的风险,高并发情景下吞吐量会大大降低!但是这种方法能够较好地降低后端存储负载,并在一致性上做得比较好。

  • “永远不过期”:这种方案由于没有设置真正的过期时间,实际上已经不存在热点key产生的一系列危害,但是会存在数据不一致的情况,同时代码复杂度会增大。

 

三、缓存雪崩

3.1什么是缓存雪崩

是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至宕机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到而从数据库查。

3.2 出现的原因

 缓存层由于某些原因不可用(宕机)或者大量缓存由于超时时间相同在同一时间段失效(大批key失效/热点数据失效),大量请求直接到达存储层,存储层压力过大导致系统雪崩

3.3解决方案 

  • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  • 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的数据缓存数据库中;把缓存层设计成高可用的,即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务。利用sentinel或cluster实现。
  • 设置热点数据永不过期。
  • 采用多级缓存,本地进程作为一级缓存,redis作为二级缓存,不同级别的缓存设置的超时时间不同,即使某级缓存过期了,也有其他级别缓存兜底
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值