如果第二次看到我的文章,欢迎文末扫码订阅我的个人公众号(跨界架构师)哟~
本文长度为2805字,建议阅读8分钟。
坚持原创,每一篇都是用心之作~
有句话说得好,欲要使其毁灭,先要使其疯狂。当你沉浸在缓存所带来的系统tps飙升的喜悦中时,使你系统毁灭的种子也已经埋在其中。
而且,你所承载的tps越高,它所带来的毁灭性更大。
在前两篇《360°全方位解读「缓存」》和《先写DB还是「缓存」?》中,我们已经对缓存有了一定的认识,并且知道了关于缓存相关的「一致性」问题的最佳实践。
这次,我们就来聊聊隐藏在缓存中的毁灭性种子是什么?
我们从前一篇文章《先写DB还是「缓存」?》中多次提到的「cache miss」说起。
缓存雪崩
在前一篇文章《先写DB还是「缓存」?》中,我们多次提到了「cache miss」这个词,利用「cache miss」来更好的保障DB和缓存之间的数据一致性。
然而,任何事物都是有两面性的,「cache miss」在提供便利的同时,也带来了一个潜在风险。
这个风险就是「缓存雪崩」。
在图中的第二步,大量的请求并发进入,这里的一次「cache miss」就有可能导致产生「缓存雪崩」。
不过,虽然「cache miss」会产生「缓存雪崩」,但「缓存雪崩」并不仅仅产生于「cache miss」。
雪崩一词源于「雪崩效应」,是指像「多米勒骨牌」这样的级联反应。前面没顶住,导致影响后面,如此蔓延。(关于对应雪崩的方式参考之前的文章,文末放链接)
所以「缓存雪崩」的根本问题是:缓存由于某些原因未起到预期的缓冲效果,导致请求全部流转到数据库,造成数据库压力过重。
因此,流量激增、高并发下的缓存过期、甚至缓存系统宕机都有可能产生「缓存雪崩」问题。
怎么解决这个问题呢?宕机可以通过做高可用来解决(可以参考之前的文章,文末放链接)。而在“流量激增”、“高并发下的缓存过期”这两种场景下,也有两种方式可以来解决。
加锁排队
通过加锁或者排队机制来限制读数据库写缓存的线程数量。比如,下面的伪代码就是对某个key只允许一个线程进入的效果。
key = "aaa"; var cacheValue = cache.read(key); if (cacheValue != null) { return cacheValue; } else { lock(key) { cacheValue = cache.read(key); if (cacheValue != null) { return cacheValue; } else { cacheValue = db.read(key); cache.set(key,cacheValue); } } return cacheValue; }
这个比较好理解,就不废话了。
缓存时间增加随机值
这个主要针对的是「缓存定时过期」机制下的取巧方案。它的目的是避免多个缓存key在同一时间失效,导致压力更加集中。
比如,你有10个key,他们的过期时间都是30分钟的话,那么30分钟后这10个key的所有请求会同时流到db去。
而这里说的这种方式就是将这10个key的过期时间打乱,比如设置成25、26、27、...、34分的过期时间,这样压力就被分散了,每分钟只有一个key过期。
最简单粗暴的方式就是在设置「过期时间」的时候加一个随机数字。
cache.set(key,cacheValue,30+random())
总体来看,相比后者,前者的适用面更广,所以Z哥建议你用「加锁排队」作为默认的通用方案不失为一个不错的选择。
「缓存穿透」、「缓存雪崩」傻傻分不清楚?
如果你听说过「缓存穿透」的话,可能会问:「缓存雪崩」和「缓存穿透」一样吗?
从产生的效果上看是一样的,但是过程不同。
来举个例子。例子纯属虚构,别太在意合理性~
在一个方圆一万里的地区内,只有一个修手机的老师傅。他收了一个徒弟,希望徒弟能帮他分担掉一部分的工作压力。这里的老师傅可以看作是DB,徒弟看作是缓存。
老师傅对徒弟说,如果遇到你不会做的事你来请教我。
然后,一个客户过来说要修一下他的卫星电话,徒弟去请教老师傅,老师傅说他也不会,先拒绝了吧。
但是由于没告诉他后续遇到修卫星电话的人该怎么做,所以后续这个客户一直来问,徒弟每次都又去请教老师傅。最终,在修卫星电话这件事上,徒弟并没有帮老师傅缓解任何的压力,快被烦死了。
上面这个故事就好比「缓存穿透」。
而「缓存雪崩」则是,由于徒弟年轻力壮,精力充沛,1小时能修20个手机,老师傅只能修10个(但是手艺好,更考究)。
然后,有一天徒弟请假了,但恰巧这天来了2000个修手机的,老师傅修不过来就被累垮了。
所以,「缓存穿透」和「缓存雪崩」最终产生的效果是一样的,就是因为大量请求流到DB后,把DB拖垮(正如前面故事中的老师傅)。
两者最大的不同在于,「缓存雪崩」问题只要数据从db中找到并放入缓存就能恢复正常(徒弟休假归来),而「缓存穿透」指的是所需的数据在DB中一直不存在的情况(老师傅也不会修)。并且,由于DB中数据不存在,所以自然每次从缓存中也找不到(徒弟也不会修)。
清楚了两者的区别之后,我们下面就来聊聊「缓存穿透」的常见应对方式。
缓存穿透
「缓存穿透」有时也叫做「缓存击穿」,产生的逻辑过程是这样,一直在虚线范围内流转。
在这种场景下,缓存的作用完全失效,每次请求都“穿透”到了DB中。
可能你会想,为什么会存在大量的这种db中数据不存在的情况呢?其实,任何依赖外部参数进行查询的地方都可能有这个问题的存在。比如,一个文本输入框,本来是让你输入用户名的,但是手误输入了密码,自然就找不到数据咯。更主要的问题是,会有恶意分子利用这种机制来对你的系统进行攻击,击穿缓存搞垮你的数据库,导致整个系统全面瘫痪。
同样也有两种方式来解决这个问题。
布隆过滤器(bloomfilter)
布隆过滤器就是由一个很长的二进制向量和一系列随机映射函数组成,将确定不存在的数据构建到过滤器中,用它来过滤请求。这里就放个图,具体就不展开了,后续我们再聊(有兴趣的可以先到搜索引擎搜《Space time trade-offs in hash coding with allowable errors》找到bloom的原始论文)。
实现代码其实并不很复杂,参考论文或者网上其他作者的一些实现就可以写出来。
不过,布隆过滤器有一个最大的缺点,也是其为了高效利用内存而付出的代价,就是无法确保100%的准确率。
所以,如果你的场景要求是100%准确的,就只能用下面这种方式了。
缓存空对象
其实就是哪怕从db中取出的数据是“空(null)”,也把它丢失到缓存中。
这样一来,虽然缓存中存在着一个value为空的数据,但是至少他能表示“数据库里也没有不用找了”。
其实这个思路和布隆过滤器有些类似,但是它对内存的消耗会大很多,毕竟布隆过滤器是利用的bit位来存储。不过这种方式的优势是前面提到的,不会出现误差,而布隆过滤器的错误率会随着「位数」的增加而减少,会不断趋近于0,但不会为0。
总结
好了,我们一起总结一下。
这次呢,Z哥主要和你聊了隐藏在缓存中的两颗具有“毁灭性”的种子,「缓存雪崩」和「缓存穿透」,以及应对这两颗种子的常用方式。
而且,顺便帮你区分清楚了「缓存雪崩」和「缓存穿透」的差异。
希望对你有所启发。
相关文章:
作者:Zachary
出处:https://www.cnblogs.com/Zachary-Fan/p/destroyseed.html
如果你喜欢这篇文章,可以下方扫码关注我的个人「原创」公众号哦。
▶关于作者:张帆(Zachary,个人微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎扫描下方的二维码~。
定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些思考。
如果你是初级程序员,想提升但不知道如何下手。又或者做程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注我的公众号「跨界架构师」,回复「技术」,送你一份我长期收集和整理的思维导图。
如果你是运营,面对不断变化的市场束手无策。又或者想了解主流的运营策略,以丰富自己的“仓库”。欢迎关注我的公众号「跨界架构师」,回复「运营」,送你一份我长期收集和整理的思维导图。
相关推荐
然而,缓存系统在实际运行中可能会遇到几种常见问题,即缓存穿透、缓存击穿和缓存雪崩。下面将详细阐述这些问题以及相应的解决方案。 **缓存穿透** 缓存穿透是指用户请求的数据在缓存和数据库中均不存在,通常是...
然而,如果使用不当,可能会遇到两种常见问题:缓存穿透和缓存雪崩。这两者都会对系统的稳定性和性能产生严重影响。 **缓存穿透** 缓存穿透是指用户请求的数据既不在Redis缓存中,也不在数据库中,导致每次请求都...
分布式系统设计模式是指在分布式系统中,为了解决如何划分服务、如何部署服务以及如何组织服务间通信等问题而采用的一些通用方案和策略。这些模式能够在不同的分布式环境和应用场景中应用,以期达到系统设计的最优解...
分布式系统架构中,使用Redis作为MyBatis的二级缓存是一种常见的优化策略,旨在...在实际开发中,还需要根据具体业务场景调整缓存策略,比如选择合适的缓存淘汰算法、设置合理的缓存大小以及考虑缓存穿透和雪崩等问题。
在面试中,对于缓存相关的知识点,面试官可能会考察你对缓存雪崩、缓存穿透、缓存预热、缓存更新以及缓存降级的理解和处理策略。以下是这些概念的详细解释: 1. **缓存雪崩** 缓存雪崩是指大量缓存在同一时刻过期...
《分布式系统原理与范型》作为一本系统介绍分布式系统基本原理与实践应用的书籍,涵盖了分布式系统设计与实现的核心理念。分布式系统指的是由多个可以独立运行的计算单元构成的系统,这些计算单元通过通信网络相互...
缓存技术在IT系统中扮演...通过校验、布隆过滤器、互斥锁以及合理的缓存过期策略,可以有效地预防缓存穿透、缓存击穿和缓存雪崩,确保系统的稳定性和高性能。同时,持续监控和优化缓存策略也是确保系统健康运行的关键。
【大型分布式系统中的缓存架构】 在大型分布式系统中,缓存是提高系统性能和响应...正确地使用缓存能够显著提升系统性能,但也会带来数据一致性、缓存穿透和雪崩等问题,因此在设计时需权衡利弊,采取适当的解决方案。
"基于Scrapy的分布式数据采集与分析——以知乎话题为例" 本文主要介绍了基于Scrapy框架的分布式数据采集与分析方法,以知乎话题为例。该方法通过实现主从式结构的分布式网络爬虫,运用开源项目Scrapy-Redis来部署...
本文将浅析分布式系统缓存设计的相关知识点,内容涵盖了缓存系统的必要性、缓存的层级、缓存面临的问题及其解决方案,以及缓存数据结构的设计和管理方法。 一、缓存系统的重要性 分布式系统缓存设计之所以重要,是...
分布式系统设计是现代互联网服务和企业级应用的核心技术之一,它涉及到多个计算机节点通过网络进行协同工作,共同处理任务和数据。在这个领域,我们需要深入理解并掌握一系列关键知识点,以构建高效、可扩展且容错的...
总结来说,理解和预防缓存雪崩和缓存穿透对于构建健壮的分布式系统至关重要。通过上述策略,我们可以显著提高系统的稳定性和可靠性。在实际应用中,还需要根据具体业务场景灵活调整和优化,确保系统在高并发情况下也...
然而,缓存系统也存在一些潜在的问题,如缓存击穿、缓存雪崩和缓存穿透,这些情况可能导致系统性能急剧下降,甚至服务中断。 **缓存击穿**是指一个非常热门的数据项在缓存中过期,这时大量的并发请求会直接冲击...
总的来说,理解Redis缓存原理,掌握缓存穿透、击穿、雪崩的预防措施,并进行模拟测试,是保证系统高可用性和性能的重要环节。开发者需要在设计缓存策略时充分考虑这些因素,确保系统的健壮性和稳定性。在实际工作中...
分布式系统是一种由多台计算机组成的网络系统,这些计算机在用户看来就像是一个单一的系统。它们通过网络互相通信和协调工作,以共同完成任务。分布式系统的设计和实现涉及许多核心概念和原则,例如透明性、开放性、...
分布式系统——从GFS到Hadoop 分布式系统是指一种可以跨越多台计算机、多个网络和多个组织的计算机系统。它可以提供高性能、可靠性和可扩展性的计算能力。分布式系统的应用非常广泛,例如云计算、大数据处理、社交...
分布式综合能源系统规划报告——.pdf
### 缓存穿透 在IT领域,特别是针对高性能和高并发的应用场景中,缓存...通过以上几种方式的综合运用,可以在很大程度上减轻缓存穿透、缓存击穿以及缓存雪崩等问题带来的负面影响,从而提高系统的整体稳定性和性能。
Redis缓存穿透、缓存雪崩、缓存击穿的原因和解决方案 Redis缓存穿透、缓存雪崩、缓存击穿是 Redis 缓存中常见的问题,它们可能会导致数据库的负载加大,影响系统的性能。本文将详细讨论这些问题的原因和解决方案。 ...