面试Redis——缓存并发 缓存雪崩 缓存穿透
积累知识,胜过积蓄金银!毕竟在##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")。浪费内存。这个时候可以结合数据校验和布隆过滤器。

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


不管如何,培养良好的开发习惯,能让你受益终身。
缓存雪崩
什么是缓存雪崩
场景:在评论列表中,如果有一批评论成为了热点评论,但不幸,此时这批条评论,在Redis缓存中,都失效了,由于没命中缓存,加上大量请求,都去数据库查询评论,从而给数据库造成极大压力,甚至崩溃。这种情况,被称为缓存雪崩。

缓存雪崩的坏处
给数据库极大压力,甚至打垮数据库,从而造成系统不能正常提供服务。
为什么会缓存雪崩
- 原因一,redis宕机,相当于多个key同一时刻失效。
- 原因二,redis没宕机,多个key正常到时就失效。
总结:如何你面试的时候,遇到这个问题,最好分情况回答,就是redis是否宕机。给面试官留下脑子清晰的印象。
解决方案
- 方案一,解决原因一,既然宕机了,那就想到高可用,redis集群,哨兵模式,故障转移和故障恢复,同时还应该做好监控和报警。如果没法自动完成故障转移,那就人工干预。
- 方案二,过期时间=失效时间+随机时间,解决原因二。
- 方案三,永不过期,既然你是因为过期时间到了导致的雪崩,那就干脆让你不过期就完事了。有人会问,那缓存一致性怎么保证?后台主动更新:就是通过mysql更新的时候,让mq监听Binlog,回调更新缓存。使其缓存和数据库数据保持一致。
- 方案四,可以从应用架构角度出发,通过限流,降级,熔断手段来降低影响,除此之外来避免多级缓存来避免这种灾难。如果你使用的微服务架构是SpringCloud,那你可以直接使用Hystrix,来实现限流,降级,熔断,修改一下配置文件即可。
补充
缓存击穿,就是只有一个key过期的缓存雪崩。
总结
全篇下来,几乎都是按照遇到报错——定位问题——分析问题——设计解决方案——解决问题方法论来写的。文中介绍了缓存并发,缓存穿透,缓存雪崩的定义,危险,原因,解决方案。大头菜希望你读完这篇文章后,不仅能学会知识,更能掌握定位问题——分析问题——解决问题的方法论。知识点,这些以后可能会忘,但方法掌握好后,方能见招拆招。
非常感谢你能看到这里,如果觉得文章写得不错 求关注 求点赞 求分享 (对我非常非常有用)。
如果你觉得文章有待提高,我十分期待你对我的建议,求留言。
如果你希望看到什么内容,我十分期待你的留言。
各位的捧场和支持,是我创作的最大动力!
好了,本文到此结束,带大家了解了《面试Redis——缓存并发 缓存雪崩 缓存穿透》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多数据库知识!
-
- 生动的小鸭子
- 这篇博文出现的刚刚好,细节满满,真优秀,码起来,关注博主了!希望博主能多写数据库相关的文章。
- 2023-03-06 11:28:36
-
- 精明的凉面
- 赞 ??,一直没懂这个问题,但其实工作中常常有遇到...不过今天到这,看完之后很有帮助,总算是懂了,感谢师傅分享文章内容!
- 2023-02-21 14:37:17
-
- 笑点低的狗
- 细节满满,码住,感谢作者的这篇文章,我会继续支持!
- 2023-02-18 00:03:48
-
- 数据库 · MySQL | 1小时前 |
- MySQL排序优化与性能提升技巧
- 153浏览 收藏
-
- 数据库 · MySQL | 3小时前 |
- MySQL中WHERE与HAVING的区别详解
- 340浏览 收藏
-
- 数据库 · MySQL | 8小时前 |
- MySQL排序优化与性能提升技巧
- 368浏览 收藏
-
- 数据库 · MySQL | 23小时前 |
- MySQL连接池配置与优化方法
- 297浏览 收藏
-
- 数据库 · MySQL | 23小时前 |
- MySQLGROUPBY使用技巧与常见问题
- 306浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL缓存优化技巧分享
- 392浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL安装到D盘教程及路径设置详解
- 279浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL缓存设置及查询作用解析
- 470浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQLcount优化技巧及性能提升方法
- 371浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQLUPDATE替换字段值方法详解
- 292浏览 收藏
-
- 数据库 · MySQL | 1天前 |
- MySQL基础:增删改查全教程
- 356浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 95次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 89次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 105次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 98次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 97次使用
-
- golang MySQL实现对数据库表存储获取操作示例
- 2022-12-22 499浏览
-
- 分享Redis高可用架构设计实践
- 2023-01-24 286浏览
-
- 搞一个自娱自乐的博客(二) 架构搭建
- 2023-02-16 244浏览
-
- B-Tree、B+Tree以及B-link Tree
- 2023-01-19 235浏览
-
- mysql面试题
- 2023-01-17 157浏览