当前位置:   article > 正文

Redis面经——深入剖析Redis缓存穿透、击穿和雪崩,一篇文章彻底拿下经典面试题

redis缓存穿透

缓存穿透(查不到数据)

一、概念
当用户想要查询一个数据,发现Redis内存数据库中没有,也就是缓存没有命中,于是向持久层数据库中查询。但是发现持久层数据库中也没有,于是本次查询失败。当用户非常多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这个现象就叫做缓存穿透

二、解决方案
1、布隆过滤器
(1)定义
在用户客户端和服务端增加了一层,这一层就是布隆过滤器。布隆过滤器的作用是查询的key先查询布隆过滤器,如果存在,则查询Redis,如果不存在,则直接返回。注意,在缓存预热的时候,也要将数据预热到布隆过滤器中

(2)布隆过滤器的工作流程图

(3)布隆过滤器底层实现
首先先了解一下位图:
bitmap(位图):相当于一个以(bit)位为单位的数组,数组中每个单元只能存储二进制0或1

布隆过滤器的作用如下:
布隆过滤器可以用于检索一个元素是否存在一个集合中
下面的案例是我想查询id为1的数据,那么key就是1。存储数据和查询数据的底层原理见下图

(4)布隆过滤器可能存在的问题
场景,我们正常存储id为1和2的数据,此时通过多次的hash计算,将对应的位置更新成1,但是此时我想查询一个id为3的数据,本身这个id为3的数据是不存在的,但是由于前面存储的1和2对应位置上的数据由0变成了1,所以布隆过滤器认为id为3是存在的

这个时候就出现一个概念叫做误判率,数组越小误判率越大,数组越大误判率越小,但是与此同时,带来了更多的内存的消耗

布隆过滤器提供了解决方案:
Redisson和Guava都提供了了对布隆过滤器的实现

在代码中直接手动设置误判率即可,下图设置的是5%,一般在真实的开发中,都是设置在5%以下就行

(5)布隆过滤器优缺点
优点:内存占用较少,没有多余的key
缺点:实现复杂,存在误判

2、缓存空对象
当存储层不命中后,即时返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源。

但是这种方法会存在两个问题:
(1)如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中会有很多空值的键

(2)即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响

缓存击穿(查得到数据,但是key即将过期)

一、概念

击穿要注意刚刚学习的缓存穿透的区别,缓存击穿,是指一个key非常热点,在不断的扛着高并发,高并发期间对这一个key进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏幕上凿开了一个洞!
当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般都是热点数据,由于缓存过期,会同时访问数据库来查询最新的数据,并且回写到缓存,会导致数据库瞬间压力过大!

二、解决方案    
1、逻辑过期(保证高可用性,性能优)
设置设点key永不过期
从缓存层面来看,没有设置过期时间,所以就不会出现热点key过期产生的严重影响!
但是一般不会这么使用,因为这个方案有可能导致Redis的空间浪费

现在升级成设置逻辑过期,实现方案如下:
假设下图的key,不给key设置过期时间,而是存储的时候,数据中增加一个逻辑过期的字段。

下图是设置逻辑过期的场景,在多线程下,缓存重现的底层逻辑

2、加互斥锁(保证强一致性,性能差)

分布式锁!!!!!!
使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此需要等待,等待拿到锁的线程将缓存重建,直接就能从Redis中命中了。这种方式将高并发的压力转到了分布式锁。保证了数据的强一致性!

缓存雪崩(key集中失效或者Redis服务宕机)

一、概念


缓存雪崩,是指在某一个时间段,缓存集中过期失效,或者是整个Redis集群宕机!


二、产生雪崩的原因
比方说在双十一的场景,马上到11月10日零点,很快就会迎来一波抢购。这波商品时间比较集中的放入了缓存中 ,假设设置了缓存的有效时间为1小时,那么到了凌晨1点,这批商品的缓存就都过期了。而对于这批商品的访问查询,都落到了数据库上,对于持久层数据库而言,就会产生周期性的压力波峰。于是所有的请求就都会达到持久层数据库,持久层数据库的调用量会暴增,可能会造成持久层数据库崩掉的情况。

其实集中过期,倒不是特别致命,比较致命的是缓存雪崩,就是缓存服务器的某个节点宕机或者断网 。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,这个时候,数据库倒是可以顶住压力。无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库造成的压力是不可预知的,很有可能瞬间就把数据库压垮!

三、解决方案
1、Redis高可用
既然Redis可能挂掉,那么就多增设几台Redis服务器节点,这样一台挂掉了其他的节点还能够正常的工作,就是搭建大的集群,开启哨兵模式

2、限流降级
给缓存业务添加降级限流策略,比如通过nginx或者Gateway。降级可作为系统的保底策略,适用于穿透。击穿和雪崩的场景

3、数据预热
在正式部署之前,可以先把可能的数据预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发量访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间尽量均匀

4、给不同的key的过期时间添加随机值

5、给业务添加多级缓存,比如使用Guava或者Caffeine
 

至此,关于经典的Redis缓存穿透、击穿和雪崩介绍完毕,后续还会继续更新Redis面经技术点,敬请期待~~~

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/823577
推荐阅读
相关标签
  

闽ICP备14008679号