Redis系列 - 缓存雪崩、击穿、穿透

前言

  从学校出来,做开发工作也有一定时间了,最近有想系统地进一步深入学习,但发现基础知识不够扎实,故此来回顾基础知识,进一步巩固、加深印象。

  最初开始接触编程时,总是自己跌跌撞撞、不断摸索地去学习,再一点点应用到实际项目中,知识点才更加清晰。后来,尝试写博客,把学到的知识试着分享出来,也是一次巩固的过程。

1、问:Redis雪崩了解吗?

  答:我了解的。目前电商首页以及热点数据都会去做缓存,一般缓存都是定时任务去刷新,或者是查不到之后去更新,定时任务刷新就有一个问题。

  举个简单例子:如果所有首页的key失效时间都是12小时,中午12点刷新,我0点开始抢单活动,大量用户涌入,假设当时每秒6000个请求,本来缓存可以扛住每秒5000个请求,但是缓存当时所有的 Key 都失效了。此时,1秒 6000个请求全部打到数据库,数据库必然扛不住,它会报一下警,但实际情况可能是DBA都没反应过来数据库就直接挂了。此时,如果没有什么特别的方案来处理这个故障,DBA很着急,重启数据库,但是数据库马上又被新的流量打死了。这就是我理解的缓存雪崩。

  同一时间缓存大面积失效,那一瞬间Redis跟没有一样,这个数量界别的请求直接打到数据库几乎是灾难性的。试想一下,如果打挂的是一个用户服务的库,那其他依赖它的库所有的接口几乎都会报错,如果没有做熔断等策略,基本上就是一瞬间挂一片的节奏,任你怎么重启用户都会把你打挂,等你重启好的时候,用户早睡觉去了,并且对我们的产品失去了信息。

2、问:那遇到这种情况,你是怎么去应对的?

  答:处理缓存雪崩相对简单,在批量往Redis存数据的时候,把每个Key的失效时间都加个随机值就好,这样就可以保证数据不会在同一时间大面积失效,我相信,Redis这点流量还是顶得住的。

setRedis( Key, value, time+Math.random() * 1000 );
  如果Redis是集群部署,将热点数据均匀分布在不同的Redis库中也能避免全部失效问题,不过在生产环境中操作集群的时候,单个服务都是对应的单个Redis分片,是为了方便数据的管理,但是也同样有可能回失效这样的弊端,失效时间随机是个好策略。

  或者设置热点数据永远不过期,用更新操作就更新缓存就好了(比如运维更新了首页商品,那你刷下缓存就完事了,不要设置过期时间),电商首页的数据也可以用这个操作,保险。

3、问:那你了解缓存穿透和击穿吗?跟雪崩有什么区别?

  答:有了解的。先说说缓存穿透吧。缓存穿透是指缓存和数据库中都没有数据,而用户不断发起请求,我们数据库的 id 都是1开始自增上去的,如果发起 id = -1 的数据 或 id 为特别大(不存在)的数据,这是用户就很可能是攻击者,攻击会导致数据库压力过大,严重会击垮数据库。

  小点的单机系统,可能用 postman 就能搞死,比如自己买的云服务。


  像这种没有对参数进行校验,数据库 ID 都是大于0的,我们一直用小于 0 的参数去请求,每次都能绕开Redis直接打到数据库,数据库也查不到,每次都这样,并发高点就容易崩掉了。

  至于缓存击穿嘛,这个和缓存雪崩有点像,但是又有点区别,缓存雪崩是因为大面积的缓存失效,打崩了DB,而缓存击穿不同的是缓存击穿是指一个Key非常热点,在不停地扛着大并发,大并发集中对一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿透缓存,直接请求数据库,就像一个完好无损的桶上凿开了一个洞。比如系统中某个商品,突然变成爆款,大量用户访问该商品,就可能发生缓存击穿。

4、问:雪崩、穿透、击穿你们都是怎么解决的?

  答:缓存穿透是请求绕过缓存直接查数据库,我会在接口层增加校验,比如对用户权限校验,接口参数做校验,不合法的参数直接Return,比如 id 做基础校验,id<=0的直接拦截等等。

  (这里我想补充一点,就是我们在开发的时候,要保持一颗“不信任”的心,就是不要相信任何调用方,比如我提供API接口出去,我需要这几个入参,那作为被调用方,任何可能的参数情况都应该被考虑到、并做校验,因为我不相信调用我接口的人,我不知道他会传什么参数给我。

  举个简单例子,我这个接口是分页查询的,但是我没有对分页参数的大小做限制,调用的人万一 一口气查 Interger.MAX_VALUE  一次请求就需要我几秒,多几个并发我接口就挂了。是公司同事调用还好,大不了发现了改掉就是了,但是如果是黑客或者竞争对手,那问题就大了。在双十一或者抢单活动的时候调用这个接口,那损失就大了。)

  从缓存取不到的数据,在数据库中也没有取到(不管是数据不存在,还是系统故障),这时也可以将对应Key的Value对写为null、“位置错误”、“稍后重试”这样的值(具体和产品沟通),或者看具体的场景,缓存的时间可以设置短点,如30秒(设置太长会导致正常情况下也没法适用),这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴

  这样可以防止攻击用户反复用同一个 id 暴力攻击,但是我们要知道正常用户是不会在单秒内发起这么多次请求的,那网关层Nginx 我们也可以添加配置项,可以让运维人员对单个 IP 每秒访问次数超出阀值的 IP 都拉黑。

5、问:还有其他办法吗?

  答:记得Redis还有一个高级用法布隆过滤器(Bloom Filter),这个也能很好地防止缓存穿透的发生,他的原理也很简单,就是利用高效的数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在你Return就好了,存在你就去查了DB刷新Key、Value,再Return。

  缓存击穿的话,设置热点数据永远不过期,或者加上互斥锁就能搞定了。(代码如下)

 1 /**
 2  * 获取数据
 3  * @param key                            查询参数
 4  * @return data                            数据
 5  * @throws InterruptedException            异常
 6  * @author    柠檬先生
 7  */
 8 public static String getData(String key) throws InterruptedException {
 9     // 从redis查询数据
10     String result = getDataFromKV(key);
11     // 校验数据
12     if (StringUtils.isBlank(result)){
13         // 获取锁
14         if (reenLock.tryLock()) {
15             // 去数据库查询
16             result = getDataFromDB(key);
17             // 校验
18             if (StringUtils.isNotBlank(result)){
19                 // 保存到缓存中;
20                 setDataToKV(key, result);
21             }
22             // *释放锁 正常会再finally里面释放;
23             reenLock.unLock();
24         }else {
25             // 睡一会儿再拿
26             Thread.sleep(100L);
27             result = getData(key);
28         }
29     }
30     return result;
31 }
32 //这里的锁是单机版玩法.,分布式锁还是得靠lua脚本这样的;

小结:

  以上介绍了Redis的雪崩、击穿、穿透,三者其实都差不多,但是又有些区别,在面试中这是问到缓存必问的,因为缓存的雪崩、击穿、穿透,是缓存最大的问题,要么不出现,一旦出现就是致命性的问题,所以面试官一定会问。

  我们学习的时候一定要理解是怎么发生,以及怎么去避免的,发生之后怎么去抢救,你可以不是了解很深入,但是你一定不能什么都不去想,面试有时候不一定是对只是面的拷问,或许是对你态度的拷问,如果你思路清晰,然后知其然还能知其所以然那就更棒了,还能知道怎么预防,那offer就是手到擒来了。

总结:

  一般避免以上情况发生我们要从3个时间段去分析:

  • 事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃;
  • 事中:本地 ehcache 缓存 + Hystrix 限流 + 降级,避免 **MySQL** 被打死。
  • 事后:Redis 持久化 RDB + AOF,一旦重启,自动从磁盘上加载数据,快速回复缓存数据。

  上面提到的限流组件,可以设置每秒的请求,有多少能通过组件,剩余未通过的请求,怎么办?走降级!可以返回一些默认值,或者友情提示,或者空白的值。

  这样做的好处是:数据库绝对不会死,限流组件确保了每秒只有多少个请求能通过。只要数据库不死,对用户来说, 3/5 的请求都是可以被处理的。只要有 3/5 的请求可以被处理,就意味着系统没有死,对用户来说,可能就是点击几次刷不出来页面,但是多点几次就可以刷出来一次。

  这个在目前主流的互联网大厂里面是最常见的,以前遇到过,某明星爆出什么事情,会发现微博怎么刷都是空白界面,但是有的人有直接进去了,多刷几次又出来了,这就是做了降级,牺牲部分用户体验来换取服务器的安全,还行。

  还有就是今年(2019)的双十一,走的就是“限流、降级”,下单接口其实没有挂,牺牲部分用户体验,保住服务器,你多点几下是可以成功的,等流量高峰过去了,所有的用户全部都恢复正常访问,服务器啥事也没有。

  去年(2018)退款接口被打崩了,今年阿里也聪明了很多,退款接口在12日0点开放,这就有效避开了流量高峰。

原文地址:https://www.cnblogs.com/qiuhaitang/p/12306382.html

时间: 2025-01-07 06:58:50

Redis系列 - 缓存雪崩、击穿、穿透的相关文章

Redis之缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级

Redis之缓存雪崩.缓存穿透.缓存预热.缓存更新.缓存降级 1.缓存雪崩 发生场景:当Redis服务器重启或者大量缓存在同一时期失效时,此时大量的流量会全部冲击到数据库上面,数据库有可能会因为承受不住而宕机 解决办法: 1)随机均匀设置失效时间 2)设置过期标志更新缓存 3)并发量不是特别多的时候,使用最多的解决方案是加锁排队 2.缓存穿透 发生场景:是指查询一个数据库一定不存在的数据.正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并

redis缓存雪崩、穿透、击穿概念及解决办法

缓存雪崩 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机.缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它会报一下警,然后就挂了.此时,如果没有采用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了. 这就是缓存雪崩. 大约在 3 年前,国内比较知名的一个互联网公司,曾因为缓存事故,导致雪崩,后台系统全部崩溃,事故从当天下午持续到晚上凌晨 3~4

Redis(一)缓存雪崩,缓存穿透,热点key的处理

1 缓存雪崩 缓存雪崩产生的原因 缓存雪崩通俗简单的理解就是:由于原有缓存失效(或者数据未加载到缓存中),新缓存未到期间(缓存正常从Redis中获取,如下图)所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机,造成系统的崩溃. 缓存失效的时候如下图: 缓存失效时的雪崩效应对底层系统的冲击非常可怕!那有什么办法来解决这个问题呢?基本解决思路如下: 第一,大多数系统设计者考虑用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,避免

阿里面试Redis最常见的三个问题:缓存击穿、雪崩、穿透(带答案)

点赞再看,养成习惯,微信搜索[三太子敖丙]我所有文章都在这里,本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点,文末有福利. 正文 上一期吊打系列我们提到了Redis的基础知识,还没看的小伙伴可以回顾一下 <吊打面试官>系列-Redis基础 那提到Redis我相信各位在面试,或者实际开发过程中对缓存雪崩,穿透,击穿也不陌生吧,就算没遇到过但是你肯定听过,那三者到底有什么区别,我们又应该怎么去防止这样的情况发生呢,我们有请下一位受害者

8.了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?

作者:中华石杉 面试题 了解什么是 redis 的雪崩.穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透? 面试官心理分析 其实这是问到缓存必问的,因为缓存雪崩和穿透,是缓存最大的两个问题,要么不出现,一旦出现就是致命性的问题,所以面试官一定会问你. 面试题剖析 缓存雪崩 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机.缓存挂了,此时 1 秒 5000 个请求全部落数

2020年3月2日的面试:什么是 redis 的雪崩、穿透和击穿?

面试题 了解什么是 redis 的雪崩.穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透? 面试官心理分析 其实这是问到缓存必问的,因为缓存雪崩和穿透,是缓存最大的两个问题,要么不出现,一旦出现就是致命性的问题,所以面试官一定会问你. 面试题剖析 缓存雪崩 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机.缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然

阿里Java面试题剖析:了解什么是 redis 的雪崩和穿透?redis 崩溃之后会怎么样?

面试原题 了解什么是 redis 的雪崩和穿透?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?面试官心理分析其实这是问到缓存必问的,因为缓存雪崩和穿透,是缓存最大的两个问题,要么不出现,一旦出现就是致命性的问题,所以面试官一定会问你. 面试题剖析 缓存雪崩对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机.缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它

redis缓存穿透,缓存击穿,缓存雪崩原因+解决方案

###一.前言在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是主页访问量瞬间较大的时候,单一使用数据库来保存数据的系统会因为面向磁盘,磁盘读/写速度比较慢的问题而存在严重的性能弊端,一瞬间成千上万的请求到来,需要系统在极短的时间内完成成千上万次的读/写操作,这个时候往往不是数据库能够承受的,极其容易造成数据库系统瘫痪,最终导致服务宕机的严重生产问题. 为了

Redis系列十:缓存雪崩、缓存穿透、缓存预热、缓存更新、缓存降级

一.缓存雪崩 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机.从而形成一系列连锁反应,造成整个系统崩溃. 缓存正常从Redis中获取,示意图如下: 缓存失效瞬间示意图如下: 缓存雪崩的解决方案: (1)碰到这种情况,一般并发量不是特别多的时候,使用最多的解决方案是加锁排队,伪代码如下: 加锁排队只是为了