缓存经典问题:缓存穿透和缓存雪崩

简介: 在某些复杂的业务场景下,单纯依靠存储系统的性能提升不够的,典型的场景如下。

【一】缓存


在某些复杂的业务场景下,单纯依靠存储系统的性能提升不够的,典型的场景如下。

(1) 需要经过复杂运算后得出的数据,存储系统无能为力。


(2) 读多写少的数据,存储系统有心无力。


缓存可以弥补存储系统在这些复杂业务场景下的不足,缓存的基本原理就是将可能重复使用的数据放到内存中,一次生成,多次使用, 避免每次使用都去访问存储系统。


Memcache缓存

缓存能够带来性能的大幅提升, 以Memcache 为例, 单台Memcache 服务器简单的key-value查询能够达到5 万以上的TPS 。缓存虽然能够大大减轻存储系统的压力,但同时也给架构引入了更多复杂性。架构设计时如果没有针对缓存的复杂性进行处理,某些场景下甚至会导致整个系统崩溃。


【二】缓存穿透


缓存穿透是指缓存没有发挥作用,业务系统虽然去缓存中查询数据,但缓存中没有数据,业务系统需要再次去存储系统中查询数据。通常情况下有两种情况: 存储数据不存在,以及生成缓存数需要耗费大量时间或资源。


• 存储数据不存在

第一种情况是被访问的数据确实不存在。一般情况下,如果存储系统中没有某个数据,则不会在缓存中存储相应的数据,这样就导致用户查询的时候,在缓存中找不到对应的数据,每次都要去存储系统中再查询一遍,然后返回数据不存在。缓存在这个场景中并没有起到分担存储系统访问压力的作用。

通常情况下, 业务上读取不存在的数据的请求量并不会太大,如果出现一些异常情况,例如, 被黑客攻击,故意大量访问某些不存在数据的业务, 有可能会将存储系统拖垮。这种情况的解决办法比较简单, 如果查询存储系统的数据没有找到, 则直接设置一个默认值( 可以是空值,也可以是具体的值)并存到缓存中, 这样第二次读取缓存时就会获取默认值,而不会继续访问存储统。


• 缓存数据生成耗费大量时间或资源


第二种情况是存储系统中存在数据,但生成缓存数据需要耗费较长时间或耗费大量资源。如果刚好在业务访问的时候缓存失效了,那么也会出现缓存没有发挥作用,访问压力全部集中在存储系统上的情况。典型的就是电商的商品分页,假设我们在某个电商平台上选择“手机”这个类别进行查看,由于数据巨大,不能把所有数据都缓存起来,只能按照分页进行缓存。由于难以预测用户到底会访问哪些分页,因此业务上最简单的就是每次点击分页的时候按分页计算和生成缓存。通常情况下这样实现是基本满足要求的,但如果被竞争对手用爬虫来遍历的时候,系统性能就可能出现问题。


具体的场景如下:

(1) 分页缓存的有效期设置为l 天, 因为设置太长时间,缓存不能反映真实的数据。

(2) 通常情况下,用户不会从第l 页到最后l 页全部看完,一般用户访问集中在前10 页,因此第10页以后的缓存过期失效的可能性很大。

(3)竞争对手每周来爬取数据,爬虫会将所有分类的所有数据全部遍历,从第1 页到最后l 页都会读取,此时很多分页缓存可能都失效了。

(4) 由于很多分页都没有缓存数据, 从数据库中生成缓存数据又非常耗费性能( order by limit 操作),因此爬虫会将整个数据库全部拖慢。

这种情况并没有太好的解决方案,因为爬虫会遍历所有的数据,而且什么时候来爬取也是不确定的, 可能每天都来,也可能每周来一次,还可能一个月来一次,我们也不可能为了应对爬虫而将所有数据永久缓存。通常的应对方案要么就是识别爬虫,然后禁止访问,但这可能影响SEO 和推广;要么就是做好监控,发现问题后及时处理,因为爬虫不是攻击,不会进行暴力破坏,对系统的影响是逐步的,监控发现问题后有时间进行处理。


【三】缓存雪崩


缓存雪崩是指当缓存失效(过期)后引起系统性能急剧下降的情况。当缓存过期被清除后,业务系统需要重新生成缓存,因此需要再次访问存储系统,再次进行运算,这个处理步骤耗时几十毫秒甚至上百毫秒。而对于一个高并发的业务系统来说,几百毫秒内可能会接到几百上千个请求。由于旧的缓存己经被清除,新的缓存还未生成,并且处理这些请求的线程都不知道另外有一个线程正在生成缓存,因此所有的请求都会去重新生成缓存,都会去访问存储系统,从而对存储系统造成巨大的性能压力。这些压力又会拖慢整个系统, 严重的会造成数据库右机,从而形成一系列连锁反应,造成整个系统崩溃。


缓存雪崩的常见解决方法有两种:更新锁机制和后台更新机制。


• 更新锁

对缓存更新操作进行加锁保护,保证只有一个线程能够进行缓存更新,未能获取更新锁的线程要么等待锁释放后重新读取缓存,要么就返回空值或默认值。对于采用分布式集群的业务系统,由于存在几十上百台服务器,即使单台服务器只有一个线程更新缓存,但几十上百台服务器一起算下来也会有几十上百个线程同时来更新缓存,同样存在雪崩的问题。因此分布式集群的业务系统要完美实现更新锁机制,需要用到分布式锁,如ZooKeeper 。

• 后台更新

由后台线程来更新缓存,而不是由业务线程来更新缓存,缓存本身的有效期设置为永久,后台线程定时更新缓存。后台定时机制需要考虑一种特殊的场景,当缓存系统内存不够时,会“踢掉” 一些缓存数据,从缓存被“踢掉”到下一次定时更新缓存的这段时间内,业务线程读取缓存返回空值,而业务线程本身又不会去更新缓存,因此业务上看到的现象就是数据丢了。


解决的方式有两种:


(1) 定时读取

后台线程除了定时更新缓存,还要频繁地去读取缓存(例如, l 秒或100 毫秒读取一次) ,

如果发现缓存被“踢了”就立刻更新缓存,这种方式实现简单,但读取时间间隔不能设置得太

长,因为如果缓存被踢了,缓存读取间隔时间又太长,则这段时间内业务访问都拿不到真正的

数据而是一个空的缓存值,用户体验一般。

(2) 消息队列通知

业务线程发现缓存失效后,通过消息队列发送一条消息通知后台线程更新缓存。可能会出现多个业务线程都发送了缓存更新消息,但其实对后台线程没有影响,后台线程收到消息后更新缓存前可以判断缓存是否存在,存在就不执行更新操作。这种方式实现依赖消息队列,复杂度会高一些,但缓存更新更及时,用户体验更好。后台更新既适应单机多线程的场景,也适合分布式集群的场景,相比更新锁机制要简单一些。后台更新机制还适合业务刚上线的时候进行缓存预热。缓存预热指系统上线后,将相关的缓存数据直接加载到缓存系统,而不是等待用户访问才来触发缓存加载。



【四】缓存热点


虽然缓存系统本身的性能比较高,但对于一些特别热点的数据,如果大部分甚至所有的业务请求都命中同一份缓存数据,则这份数据所在的缓存服务器的压力也很大。例如,某明星微博发布“我们”来宣告恋爱了,短时间内上千万的用户都会来围观。缓存热点的解决方案就是复制多份缓存,将请求分散到多个缓存服务器上,减轻缓存热点导致的单台缓存服务器压力。以新浪微博为例,对于粉丝数超过100 万的明星,每条微博都可以生成100 份缓存,缓存的数据是一样的,通过在缓存的key里面加上编号进行区分,每次读缓存时都随机读取其中某份缓存。


相关文章
|
1月前
|
存储 缓存 监控
缓存击穿、缓存穿透、缓存雪崩 3大问题,如何彻底解决?
【10月更文挑战第8天】在分布式系统中,缓存的使用极大地提高了系统的性能和响应速度。然而,缓存击穿、缓存穿透和缓存雪崩是三个常见的缓存相关问题,它们可能导致系统性能下降,甚至引发系统崩溃。本文将深入探讨这三个问题的成因、影响以及彻底的解决方案。
75 1
|
1月前
|
缓存 NoSQL 关系型数据库
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
本文深入探讨了Redis缓存的相关知识,包括缓存的概念、使用场景、可能出现的问题(缓存预热、缓存穿透、缓存雪崩、缓存击穿)及其解决方案。
182 0
redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿
|
3月前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
10天前
|
缓存 NoSQL 关系型数据库
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
本文详解缓存雪崩、缓存穿透、缓存并发及缓存预热等问题,提供高可用解决方案,帮助你在大厂面试和实际工作中应对这些常见并发场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:如何解决Redis缓存雪崩、缓存穿透、缓存并发等5大难题
|
23天前
|
存储 缓存 监控
利用 Redis 缓存特性避免缓存穿透的策略与方法
【10月更文挑战第23天】通过以上对利用 Redis 缓存特性避免缓存穿透的详细阐述,我们对这一策略有了更深入的理解。在实际应用中,我们需要根据具体情况灵活运用这些方法,并结合其他技术手段,共同保障系统的稳定和高效运行。同时,要不断关注 Redis 缓存特性的发展和变化,及时调整策略,以应对不断出现的新挑战。
58 10
|
23天前
|
缓存 监控 NoSQL
Redis 缓存穿透的检测方法与分析
【10月更文挑战第23天】通过以上对 Redis 缓存穿透检测方法的深入探讨,我们对如何及时发现和处理这一问题有了更全面的认识。在实际应用中,我们需要综合运用多种检测手段,并结合业务场景和实际情况进行分析,以确保能够准确、及时地检测到缓存穿透现象,并采取有效的措施加以解决。同时,要不断优化和改进检测方法,提高检测的准确性和效率,为系统的稳定运行提供有力保障。
48 5
|
23天前
|
缓存 监控 NoSQL
Redis 缓存穿透及其应对策略
【10月更文挑战第23天】通过以上对 Redis 缓存穿透的详细阐述,我们对这一问题有了更深入的理解。在实际应用中,我们需要根据具体情况综合运用多种方法来解决缓存穿透问题,以保障系统的稳定运行和高效性能。同时,要不断关注技术的发展和变化,及时调整策略,以应对不断出现的新挑战。
42 4
|
1月前
|
存储 缓存 NoSQL
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
大数据-38 Redis 高并发下的分布式缓存 Redis简介 缓存场景 读写模式 旁路模式 穿透模式 缓存模式 基本概念等
62 4
|
1月前
|
消息中间件 缓存 NoSQL
大数据-49 Redis 缓存问题中 穿透、雪崩、击穿、数据不一致、HotKey、BigKey
大数据-49 Redis 缓存问题中 穿透、雪崩、击穿、数据不一致、HotKey、BigKey
53 2
|
2月前
|
缓存 NoSQL Redis
解决 Redis 缓存穿透问题的有效方法
解决 Redis 缓存穿透问题的有效方法
53 2