一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第1张图片

 

相关历史文章(阅读本文之前,您可能需要先看下之前的系列

 

国内最全的Spring Boot系列之三

「世界上最好的学习法:费曼学习法」

高并发,不怕不怕「限流算法第一把法器:计数器法」 - 第300篇

精度不够,滑动时间来凑「限流算法第二把法器:滑动时间窗口算法」- 第301篇

没有预热,不叫高并发「限流算法第三把法器:令牌桶算法」- 第302篇

水满自溢「限流算法第四把法器:漏桶算法」- 第303篇

 

 

悟纤:师傅,我前几天去面试,被面试官虐的不行。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第2张图片

师傅:是不是觉得面试官虐你千百遍,你还得待她为初恋一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第3张图片

悟纤:可不,我还不敢说啥,还得好好说话。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第4张图片

师傅:缓存穿透、缓存击穿、缓存雪崩,这些名词那是高大上上档次,但是实际实际很简单的。你要不会,待为师用我帅帅的姿势和你讲解下。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第5张图片

悟纤:师傅,那还不赶紧来。听完课还要出去浪呐!

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第6张图片


 

一、缓存架构图

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第7张图片

(1)在没有引入缓存的时候,我们请求的数据都是上数据库直接查询了。

(2)引入缓存之后,我们在获取数据时会先去缓存看看有没有缓存数据,有直接返回,没有上数据库进行查询,然后设置到缓存中,再进行返回。

(3)并不是所有的数据都要放到缓存中了:访问频率低的、读少写多的、一致性要求高的,这些就不要缓存了。

 

二、缓存穿透、击穿、雪崩

2.1 缓存穿透

师傅:纳尼,不是做缓存了,怎么还一直请求到数据库?

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第8张图片

 

悟纤:你不会告诉我这就是缓存穿透吧?

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第9张图片

 

师傅:是的,这就是缓存穿透造成的结果。

师傅:我们先来看下缓存穿透的定义吧,如下:

缓存穿透:在高并发下,查询一个不存在的值时,缓存不会被命中,导致大量请求直接落到数据库上,如活动系统里面查询一个不存在的活动。

师傅:这个名词取的多形象呐,缓存穿透。

师傅:你从何而来,要到到何处,从缓存过来,到数据库去。直接从缓存穿、透过去了,有点是绕开了缓存的意思一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第10张图片

 

悟纤:师傅这是一语道破天机呐。

师傅:简单说就是,

缓存穿透请求未命中缓存,直接到数据库,这就是缓存穿透。比如:查询一个不存在的值的时候,如发起为id为“-1”的数据或id为特别大不存在的数据

师傅:明白了,一箭穿心,就是直接从缓存系统传过去,透到数据库,就是缓存穿透。一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第11张图片

 

2.2 缓存击穿

师傅:理解了缓存击穿,接下来咱们来讲缓存击穿,注意这两个差别。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第12张图片

 

师傅:缓存穿透是查询一个不存在的数据,导致每次都打到数据库上了。缓存击穿,是确实在缓存有数据,我很用心的给你传了一个活动id = 666的。

悟纤:那怎么还会有问题呐?这不是很好嘛,每次请求都命中缓存了,使用率很高耶。

师傅:师傅,徒儿你还是太嫩了,还得在吃几年草。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第13张图片

 

悟纤:师傅,你又逗徒儿开心了,我不是你的小宝贝嘛。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第14张图片

 

师傅:(*^▽^*) , 你想想缓存是有失效时间的吧,那么如果缓存刚好到期了,而此时有一万个麒麟臂向你扑面而来,哦,不,是有大量请求过来,直接打到了数据库。看看定义吧:

缓存击穿:缓存中的一个Key(比如一个促销商品),在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。

师傅:一般这样的key都是热点key,玩过秒杀,秒杀中的key就是热点key。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第15张图片

悟纤:师傅我懂了,就是热点key在高并发下刚好过期了,这些秒级请求直接打到数据库,如果数据库处理不过来,那就挂了。

师傅:嗯嗯,很对,所以缓存击穿简单理解就是:

缓存击穿热点key,缓存过期,直击数据库。比如:秒杀活动的时候,大量用户进行抢购某个商品,而此时刚好key过期了,那么这些请求就直接命中到数据库了。

师傅:我们在来从词理解下这个意思。你看缓存击穿,何谓击穿,不就是有一个东西顶着,然后没顶住,就穿过去了嘛。请求击倒缓存,缓存碰巧开小差了下,就穿到数据库了。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第16张图片

 

 

2.3 缓存雪崩

师傅:我们先理解下雪崩的意思,大量雪体崩塌,这种自然想象就是雪崩。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第17张图片

悟纤:这个我也知道,那和我们的缓存有什么关系呢。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第18张图片

 

师傅:你看,大量雪对应缓存中的就是大量的key,崩塌就是缓存过期失效了,这就造成缓存雪崩了,直接请求到数据库了,同样的我们看下定义。

缓存雪崩:大量的缓存key在同一时间失效,导致大量的请求落到数据库上,如活动系统里面同时进行着非常多的活动,但是在某个时间点所有的活动缓存全部过期。

BTW:击穿与雪崩的区别即在于击穿是对于某一特定的热点数据来说,而雪崩是全部数据。

 

 

三、缓存穿透、击穿、雪崩进阶理解

3.1 理解一

师傅:徒儿,你看我们上面介绍的定义,发现什么规律没有?

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第19张图片

 

悟纤:递进关系。

师傅:也有点那么点关系,上面在介绍的是从无到有,再到多的一种方式。

师傅:来,跟上师傅的思路,当我们正常使用缓存的时候,设置key,获取key。这个使用起来不会有啥问题,但是攻击者不乖哦,就不按照正常路子来,要么不来,要么就多来了。

悟纤:师傅,你把我都整蒙了,请hello world的语言和我说下好不。

师傅:当“无key”的时候,也就是key不存在,这时候频繁请求,就会越过缓存,造成缓存穿透。

师傅:当“有一key”且很“火热”的时候,也就是热点key,这时候频繁请求,碰巧缓存过期了,就会造成缓存击穿。

师傅:当“有多key”的时候,也就是说大量的key,在同一时间失效了,欧侯,这时候就都请求到数据库了,这就会造成缓存雪崩了。

 

3.2 理解二

       我们也可以这么理解,上面缓存的三种情况,就是在缓存在高并发下的并发问题。

       高并发下,不停的访问一个不存在的key,造成请求绕过了缓存系统,请求落到了数据库,就造成了缓存穿透。

       高并发下,不停的访问一个热点key,在缓存失效的时候,请求在此时落到了数据库,就造成了缓存击穿(缓存击穿,本来是有人挡着的,但是利用了缓存失效的间隙,进行了攻击)。

       高并发下,大批量缓存的key同时失效,此时所有请求落到了数据库,造成数据库压力过大,这就是缓存雪崩。

 

四、缓存穿透、击穿、雪崩如何解决?

4.1 缓存穿透如何解决?

(1)在接口层增加校验,比如用户鉴权校验,参数做校验,不合法的参数直接代码Return,比如:id 做基础校验,id <=0的直接return。

(2)缓存NULL值,但是缓存NULL的时间不能太长,否则NULL数据长时间得不到更新,也不能太短,否则达不到防止缓存击穿的效果。

(3)布隆过滤器(Bloom Filter):类似于哈希表的一种算法,用所有可能的查询条件生成一个bitmap,在进行数据库查询之前会使用这个bitmap进行过滤,如果不在其中则直接过滤,从而减轻数据库层面的压力。

 

4.2 缓存击穿如何解决?

(1)设置热点数据永远不过期

(2)使用加互斥锁:对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询。

public String get(key) {
	      String value = redis.get(key);
	      if (value == null) { //代表缓存值过期
	          //假设设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load db
	      if (redis.setnx(key_mutex, 1, 3 * 60) == 1) {  //代表设置成功
	               value = db.get(key);
	                      redis.set(key, value, expire_secs);
	                      redis.del(key_mutex);
	              } else {  //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可
	                      sleep(50);
	                      get(key);  //重试
	              }
	          } else {
	              return value;      
	          }
	 }

 

4.3 缓存雪崩如何解决?

(1)缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。

(2)设置热点数据永远不过期。

 

五、悟纤小结

悟纤:师傅,你是在太牛逼了,终于知道你为哈要剃个光头了 —— 聪明绝顶了。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第20张图片

师傅:几天没打你,你这是又皮痒了吧。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第21张图片

 

悟纤:师傅,徒儿不敢,徒儿这本意是要表达对师傅的培养,不想词穷…

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第22张图片

 

师傅:就你这机灵的脑瓜,如果用在学习上,你早就超过师傅了。

悟纤:师傅说的是,那我给师傅总结下今天讲的内容吧,以表我认真学习的决心。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第23张图片

 

(1)缓存穿透:查询一个不存在的值时,未命中缓存,直接落到了数据库。解决方案:接口校验、缓存NULL值、Bloom Filter。

(2)缓存击穿:热点key,缓存过期,直击数据库。解决方案:设置永不过期、加锁互斥获取数据。

(3)缓存雪崩:大量的缓存key在同一时间失效,导致大量请求落到数据库上。解决方案:设置用不过期、随机过期时间。

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第24张图片

我就是我,是颜色不一样的烟火。
我就是我,是与众不同的小苹果。

学院中有Spring Boot相关的课程:

à悟空学院:https://t.cn/Rg3fKJD

SpringBoot视频:http://t.cn/A6ZagYTi

Spring Cloud视频:http://t.cn/A6ZagxSR

SpringBoot Shiro视频:http://t.cn/A6Zag7IV

SpringBoot交流平台:https://t.cn/R3QDhU0

SpringData和JPA视频:http://t.cn/A6Zad1OH

SpringSecurity5.0视频:http://t.cn/A6ZadMBe

Sharding-JDBC分库分表实战:http://t.cn/A6ZarrqS

分布式事务解决方案「手写代码」:http://t.cn/A6ZaBnIr

JVM内存模型和性能调优:http://t.cn/A6wWMVqG

 

一分钟get:缓存穿透、缓存击穿、缓存雪崩 - 第304篇_第25张图片

http://t.cn/A6wWMVqG

你可能感兴趣的:(从零开始学Spring,Boot,spring,boot,java)