当前位置:首页 > 文章列表 > 数据库 > MySQL > 面试Redis——缓存并发 缓存雪崩 缓存穿透

面试Redis——缓存并发 缓存雪崩 缓存穿透

来源:SegmentFault 2023-02-16 15:36:55 0浏览 收藏

积累知识,胜过积蓄金银!毕竟在##column_title##开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《面试Redis——缓存并发 缓存雪崩 缓存穿透》,就带大家讲解一下MySQL、Redis、Java、数据库、后端知识点,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~

本文主要叙述缓存并发,缓存雪崩,缓存穿透的问题以及解决方案。

缓存并发

什么是缓存并发

场景:在你每天刷抖音,看微信短视频时,都会有一个评论列表,在评论列表中,查询评论的时候,会先去查询Redis缓存,如果有,就立即返回;如果没,就去数据库查询数据,接着更新缓存,返回数据。这时候,如果访问量非常多,有多个C端同时查询评论,Redis缓存又恰好没缓存数据,此时,多个C端就会同时去查询数据库。上述这种现象,就被称为缓存并发。

命中缓存(图片摘自网络)

缓存失效或宕机(图片摘自网络)
话说回来,缓存并发会带来什么危害
  • 让数据库的压力剧增,因为数据库抗不了高并发,流量再大一点,可以直接被打垮,对用户极其不友好,在如今互联网上,App应用的被替代率是很高的,稍有不慎,用户就会被其他App抢走,这对企业来说是灾难性的。我们可以知道,Redis这玩意儿,要么不出问题,一出问题,肯定是大问题。这也就是为什么要强调知其然知其所以然的原因。
既然我们已经知道缓存并发的的严重性,那如何解决
  • 要解决问题前,我们得分析问题为何会产生。絮叨一下,很多人无论是在面试时或者工作时,遇到问题,就立马改,或者说按照百度给的方法就套上去试,这个不行,试那个。这种解决问题的方式是不正确的。一般解决问题的方法论是:遇到报错——定位问题——分析问题——设计解决方案——解决问题。回到缓存并发问题上,我们分析一下“为什么出现缓存并发”。

为什么会缓存并发

  • 原因一:在高并发场景下,机器刚刚启动,且没预热缓存,缓存都为空,又没用分布式锁
  • 原因二:在高并发场景下,机器运行已运行一段时间,但缓存刚好失效,又没用分布式锁
  • 原因三:在高并发场景下,Redis宕机了

以上3种原因都会产生缓存并发,如有遗漏其他原因,欢迎各位同学在留言区补充。

知道原因后,我们可以对照原因来设计解决方案了。

解决方案

  • 针对原因一和原因二,方案 :分布式锁。这个允许一个线程去请求数据库,其他线程挂起,线程查完数据库后,更新缓存,其他线程去访问缓存,返回数据。至于分布式锁如何使用和其底层实现,其实有比较多的细节注意的,但这里不过多讲解,后续会陆续出对应的文章,如果你安耐不住寂寞,可以去谷歌一下。
  • 针对原因三,方案:Redis的高可用。说到高可用,无非就是主从结构+哨兵模式,或者Redis集群。(加链接)

分布式锁和Redis高可用,其实是预防措施,这些应该是事前工作。如果现在缓存并发确实已经发生了,能做的就是把这个模块服务的流量入口缩小,以免因这个模块服务流量过大把MySQL直接打死,从而导致其他模块服务受到影响。如果是Redis宕机了,先把流量入口缩小,然后赶紧重启机器。

当然,最好是事前做好Hystrix的限流、降级、拒绝服务等工作。限流和降级,限流,顾名思义就是限制流量,允许多少流量可以通过,比如每秒最多1000。超过1000后的请求,就走降级,比如返回一些默认值或者友情提示:目前系统繁忙,稍后重试。拒绝服务,则是最后一道防线,如果流量持续一段时间后,仍然很大,就直接拒绝服务,拒绝服务是为了保护Redis直接被流量一波带走,如果Redis服务被打死后,恢复是比较耗费时间的,而且也会因为流量一直很大,刚重启,流量一波又直接带走Redis,完成双杀,Double Kill。拒绝服务,会等流量小后,较快恢复回正常服务状态。拒绝服务是迫不得已之举。

当初大头菜初入互联网行业时,乳臭未干,什么也不懂,用Redis前,只知道Redis很厉害,很适合做缓存,关于Redis的注意事项,除了知道在生产环境不能用keys *命令外,其他一概不懂。当时的评论项目,因为流量特别大,并发贼高,查询评论接口就出现了缓存并发问题,幸好提前做了默认值回复和限流+降级措施。下面是用分布式锁解决缓存并发的关键代码:

  @Autowired
  private DistributionLock locker;
  
 //没缓存,查数据库,获取评论
  if (comment == null) {
      //加分布式锁,只允许一个线程去回源
      if(locker.trylock(Constants.QUERYCOMMENT+moduleType+resourceId)){
          try {
              comment = getDataFromRedis(moduleType, resourceId);
              if(comment == null){
                  //缓存没数据,去数据库查
                  comment = getDataFromMongoDB(moduleType, resourceId);
              }
          }finally {
              locker.unlock(Constants.QUERYCOMMENT+moduleType+resourceId);
          }
      }

分布式锁(图片摘自网络)

接下来,继续讲缓存穿透

缓存穿透

什么是缓存穿透

场景:查询评论的时候,如果直接查询id=-1的数据,那么在缓存中,没命中,又去数据库中查找,又没命中。上述这种情况,被称为缓存穿透。用通俗易懂的话来概括:就是查找一个一定不存在数据库的数据,就叫缓存穿透。

那缓存穿透有什么坏处呢
  • 如果流量大时,会直接打趴服务,造成服务不可用。

按照方法论的套路继续走

为什么会出现缓存穿透
  • 原因一,非正常请求,比如:黑客攻击,专门构造一些特殊格式的数据来请求,给系统造成巨大压力。
  • 原因二,正常请求,用户输错了数据。

解决方案

  • 方案一:缓存空对象:在请求时,先访问缓存,查不到数据,再去数据库查询,数据库也查不到对应的数据,返回null给客户端。且异步更新缓存(key,“null”),并加入短暂的过期时间。

缓存空对象(图片摘自网络)
  • 方案二:方案一其实有一个明显的缺点,就是如果请求的数据一定不存在时,那么这个时候,缓存就缓存一大堆无用的(key1,"null"),(key2,"null")。浪费内存。这个时候可以结合数据校验和布隆过滤器。

布隆过滤器(图片摘自网络)

说到数据校验,这个事儿是特别重要的。尤其是在一些直接涉及到钱的服务中,数据校验是巨重要的。如果不进行数据校验,大公司的老板就少一台宾利。小公司,就可能直接破产了。下面是大头菜的同学所在公司的案例

案例

案例-1

不管如何,培养良好的开发习惯,能让你受益终身。

缓存雪崩

什么是缓存雪崩

场景:在评论列表中,如果有一批评论成为了热点评论,但不幸,此时这批条评论,在Redis缓存中,都失效了,由于没命中缓存,加上大量请求,都去数据库查询评论,从而给数据库造成极大压力,甚至崩溃。这种情况,被称为缓存雪崩。

缓存雪崩(图片摘自网络)
缓存雪崩的坏处

给数据库极大压力,甚至打垮数据库,从而造成系统不能正常提供服务。

为什么会缓存雪崩

  • 原因一,redis宕机,相当于多个key同一时刻失效。
  • 原因二,redis没宕机,多个key正常到时就失效。
总结:如何你面试的时候,遇到这个问题,最好分情况回答,就是redis是否宕机。给面试官留下脑子清晰的印象。

解决方案

  • 方案一,解决原因一,既然宕机了,那就想到高可用,redis集群,哨兵模式,故障转移和故障恢复,同时还应该做好监控和报警。如果没法自动完成故障转移,那就人工干预。
  • 方案二,过期时间=失效时间+随机时间,解决原因二。
  • 方案三,永不过期,既然你是因为过期时间到了导致的雪崩,那就干脆让你不过期就完事了。有人会问,那缓存一致性怎么保证?后台主动更新:就是通过mysql更新的时候,让mq监听Binlog,回调更新缓存。使其缓存和数据库数据保持一致。
  • 方案四,可以从应用架构角度出发,通过限流,降级,熔断手段来降低影响,除此之外来避免多级缓存来避免这种灾难。如果你使用的微服务架构是SpringCloud,那你可以直接使用Hystrix,来实现限流,降级,熔断,修改一下配置文件即可。

补充

缓存击穿,就是只有一个key过期的缓存雪崩。

总结

全篇下来,几乎都是按照遇到报错——定位问题——分析问题——设计解决方案——解决问题方法论来写的。文中介绍了缓存并发,缓存穿透,缓存雪崩的定义,危险,原因,解决方案。大头菜希望你读完这篇文章后,不仅能学会知识,更能掌握定位问题——分析问题——解决问题的方法论。知识点,这些以后可能会忘,但方法掌握好后,方能见招拆招。

非常感谢你能看到这里,如果觉得文章写得不错 求关注 求点赞 求分享 (对我非常非常有用)。
如果你觉得文章有待提高,我十分期待你对我的建议,求留言。
如果你希望看到什么内容,我十分期待你的留言。
各位的捧场和支持,是我创作的最大动力!

好了,本文到此结束,带大家了解了《面试Redis——缓存并发 缓存雪崩 缓存穿透》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多数据库知识!

版本声明
本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
大体量数据迁移思路大体量数据迁移思路
上一篇
大体量数据迁移思路
玩转java8 Lambda表达式一
下一篇
玩转java8 Lambda表达式一
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    508次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • 笔灵AI生成答辩PPT:高效制作学术与职场PPT的利器
    笔灵AI生成答辩PPT
    探索笔灵AI生成答辩PPT的强大功能,快速制作高质量答辩PPT。精准内容提取、多样模板匹配、数据可视化、配套自述稿生成,让您的学术和职场展示更加专业与高效。
    4次使用
  • 知网AIGC检测服务系统:精准识别学术文本中的AI生成内容
    知网AIGC检测服务系统
    知网AIGC检测服务系统,专注于检测学术文本中的疑似AI生成内容。依托知网海量高质量文献资源,结合先进的“知识增强AIGC检测技术”,系统能够从语言模式和语义逻辑两方面精准识别AI生成内容,适用于学术研究、教育和企业领域,确保文本的真实性和原创性。
    17次使用
  • AIGC检测服务:AIbiye助力确保论文原创性
    AIGC检测-Aibiye
    AIbiye官网推出的AIGC检测服务,专注于检测ChatGPT、Gemini、Claude等AIGC工具生成的文本,帮助用户确保论文的原创性和学术规范。支持txt和doc(x)格式,检测范围为论文正文,提供高准确性和便捷的用户体验。
    26次使用
  • 易笔AI论文平台:快速生成高质量学术论文的利器
    易笔AI论文
    易笔AI论文平台提供自动写作、格式校对、查重检测等功能,支持多种学术领域的论文生成。价格优惠,界面友好,操作简便,适用于学术研究者、学生及论文辅导机构。
    35次使用
  • 笔启AI论文写作平台:多类型论文生成与多语言支持
    笔启AI论文写作平台
    笔启AI论文写作平台提供多类型论文生成服务,支持多语言写作,满足学术研究者、学生和职场人士的需求。平台采用AI 4.0版本,确保论文质量和原创性,并提供查重保障和隐私保护。
    32次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码