16)缓存雪崩、缓存击穿、缓存穿透

简介: 16)缓存雪崩、缓存击穿、缓存穿透


楔子



在使用 Redis 时,会面临缓存雪崩缓存穿透缓存击穿等问题,无论哪一个发生,都会导致大量请求打到数据库。如果数据库宕机,那就是很严重的事故了。

下面我们就来分析一下,这几个问题产生的原因以及解决办法。


缓存雪崩



缓存雪崩是指在短时间内,有大量缓存同时过期,导致大量请求直接查询数据库,从而对数据库造成了巨大的压力,严重情况下可能会导致数据库宕机。这种情况就叫做缓存雪崩。

以上对比图可以看出缓存雪崩对系统造成的影响,那么问题来了,缓存雪崩是如何产生的呢?

  • 缓存中有大量 key 同时过期,导致相应的请求会打到数据库;
  • Redis 实例宕机了;

而问题的解决方式也很简单,首先来看第一种情况。

1)当大量 key 同时过期时。

为了避免缓存同时过期,可在设置缓存时额外添加一个随机时间,这样一来数据的过期时间会有所差别,但差别又不会太大。即避免了大量的缓存同时失效,又能满足业务功能。

除了微调过期时间之外,还可以通过服务降级。而所谓的服务降级就是指,在服务器资源不够、或者说压力过大时,将一些非核心服务暂停,优先保证核心服务的运行。比如:

  • 当业务应用访问的是非核心数据(例如电商商品属性)时,暂时停止从缓存中查询这些数据,而是直接返回预定义信息、空值或是错误信息;
  • 当业务应用访问的是核心数据(例如电商商品库存)时,仍然允许查询缓存,如果缓存缺失,也可以继续通过数据库读取;

这样一来,只有部分过期数据的请求会发送到数据库,数据库的压力就没有那么大了。

另外还设计二级缓存,也就是除了 Redis 之外,再设置一层缓存,当缓存失效之后,先去查询二级缓存。

2)Redis 实例宕机。

实例宕机相比缓存雪崩要更加严重,一般来说一个 Redis 实例可以支持数万级别的请求处理吞吐量,而单个数据库可能只支持数千级别的请求处理吞吐量,它们两个的处理能力至少相差了近十倍。由于 Redis 缓存失效,所以数据库就可能要承受近十倍的请求压力,从而因为压力过大而崩溃。

这个时候,可以进行服务熔断。服务熔断指的是在发生缓存雪崩时,为了防止引发数据库雪崩,甚至是整个系统的崩溃,我们暂停业务应用对缓存系统的接口访问。再具体点说,就是业务应用调用缓存接口时,缓存客户端并不把请求发给 Redis 缓存实例,而是直接返回,等到 Redis 缓存实例重新恢复服务后,再允许应用请求发送到缓存系统。

这样一来,我们就避免了大量请求因缓存缺失,而积压到数据库系统,保证了数据库系统的正常运行。

在业务系统运行时,我们可以监测 Redis 缓存所在机器和数据库所在机器的负载指标,例如每秒请求数、CPU 利用率、内存利用率等。如果我们发现 Redis 缓存实例宕机了,而数据库所在机器的负载压力突然增加(例如每秒请求数激增),说明就发生缓存雪崩了,大量请求被发送到数据库进行处理。我们可以启动服务熔断机制,暂停业务应用对缓存服务的访问,从而降低对数据库的访问压力。

因此服务熔断虽然可以保证数据库的正常运行,但是暂停了整个缓存系统的访问,对业务应用的影响范围大。为了尽可能减少这种影响,我们也可以进行请求限流。也就是在业务系统的请求入口前端,通过加锁排队的方式控制每秒进入系统的请求数,避免过多的请求被发送到数据库。

假设业务系统正常运行时,请求入口前端允许每秒进入系统的请求是 1 万个,其中 9000 个请求都能在缓存系统中进行处理,只有 1000 个请求会被应用发送到数据库进行处理。

然而一旦 Redis 宕机,数据库的每秒请求数会突然增加到每秒 1 万个,此时我们就可以启动请求限流机制,在请求入口前端只允许每秒进入系统的请求数为 1000 个,再多的请求就会在入口前端被直接拒绝服务。所以使用了请求限流,就可以避免大量并发请求压力传递到数据库层。

所以使用服务熔断或是请求限流机制,来应对 Redis 实例宕机导致的缓存雪崩问题,是属于事后诸葛亮。也就是已经发生非常严重的缓存雪崩了(实例宕机了),我们使用这两个机制,来降低雪崩对数据库和整个业务系统的影响。而我们也可以提前预防,也就是通过主从复制的方式,搭建 Redis 高可用集群,主节点挂了就切换到从节点。

所以当发生缓存雪崩时,解决方案如下:

  • 随机化过期时间;
  • 服务降级;
  • 设置二级缓存;
  • 服务熔断(Redis 实例宕机,问题很严重了);
  • 请求限流(相比服务熔断,限流的影响要小一些,它还允许一部分请求过来,交给数据库来处理);
  • 搭建 Redis 集群;


缓存击穿



缓存击穿指的是热点数据在某一时刻失效了,然后有大量的并发请求要访问热点数据,但由于数据已失效,于是这些请求就会全部打到数据库,从而给数据库造成巨大的压力,这种情况就叫做缓存击穿。

缓存击穿的执行流程如下图所示:

它的解决方案有以下两个:

1)加锁排队

此处理方式和缓存雪崩加锁排队的方法类似,都是在查询数据库时加锁排队,以此来减少服务器的运行压力。

但缓存击穿只是热点数据失效,所以我们有更加优雅的方式解决。

2)永不过期

对于某些热点缓存,我们可以设置永不过期,这样就能保证缓存的稳定性。但需要注意:在数据更改之后,要及时更新此热点缓存,不然就会造成查询结果的误差。


缓存穿透



缓存穿透是指查询数据库和缓存都无数据,因为数据库查询无数据,出于容错考虑,不会将结果保存到缓存中。因此每次请求都会去查询数据库,这种情况就叫做缓存穿透。

那么缓存穿透会在什么时候发生呢?

  • 业务层误操作:缓存中的数据和数据库中的数据被误删除了,所以缓存和数据库中都没有数据;
  • 恶意攻击:专门访问数据库中没有的数据;


缓存穿透会给数据库造成很大的压力,而缓存穿透的解决方案有以下几个。

1)缓存空值或缺省值

一旦发生缓存穿透,我们就可以针对查询的数据,在 Redis 中缓存一个空值或是和业务层协商确定的缺省值(例如,库存的缺省值可以设为 0)。后续应用发送请求进行查询时,就可以直接从 Redis 中读取空值或缺省值,然后返回。从而避免把大量请求发送给数据库处理,保证了数据库的正常运行。

但为了提高前台用户的使用体验 (解决长时间内查询不到任何信息的情况),但是我们可以将空结果的缓存时间设置得短一些,例如 3~5 分钟,以防止无用数据过多。

2)使用布隆过滤器

关于布隆过滤器我们后面会说,总之它的特点就是:如果布隆过滤器检测数据存在,那么数据有可能不存在;但如果布隆过滤器检测数据不存在,那么数据一定不存在。

如果数据不存在,那么就不会查询数据库了,这样一来即使发生缓存穿透,也不会影响数据库。布隆过滤器可使用 Redis 实现,本身就能承担较大的并发访问压力。

3)在请求入口的前端进行检测

缓存穿透的一个原因是有大量的恶意请求访问不存在的数据,所以一个有效的应对方案是在请求入口前端,对业务系统接收到的请求进行合法性检测,把恶意的请求(例如请求参数不合理、请求参数是非法值、请求字段不存在)直接过滤掉,不让它们访问后端缓存和数据库。这样一来,也就不会出现缓存穿透问题了。

跟缓存雪崩、缓存击穿这两类问题相比,缓存穿透的影响更大一些。从预防的角度来说,我们需要避免误删除数据库和缓存中的数据;从应对角度来说,我们可以在业务系统中使用缓存空值或缺省值、使用布隆过滤器,以及进行恶意请求检测等方法。


缓存预热



再补充一下缓存预热,首先缓存预热并不是一个问题,而是使用缓存时的一个优化方案,它可以提高前台用户的使用体验。

缓存预热指的是在系统启动的时候,先把查询结果预存到缓存中,以便用户后面查询时可以直接从缓存中读取,节约用户的等待时间。

缓存预热的实现思路有以下三种:

  • 把需要缓存的方法写在系统初始化的方法中,这样系统在启动的时候就会自动的加载数据并缓存数据;
  • 把需要缓存的方法挂载到某个页面或后端接口上,手动触发缓存预热;
  • 设置定时任务,定时自动进行缓存预热;


小结



缓存雪崩、缓存击穿、缓存穿透三者都比较类似,缓存雪崩是大量的 key 同时失效,导致请求全部访问数据库;而缓存击穿是某个 key、只不过是热点 key 失效了,同样导致大量请求访问数据库;缓存穿透是大量请求访问不存在的 key,导致数据库压力增大。

因此这三者是比较相似的,它们的解决方案如下:

最后再说一下,服务熔断、服务降级、请求限流这些方法都是属于有损方案,在保证数据库和整体系统稳定的同时,会对业务应用带来负面影响。

如使用服务降级时,数据的部分就只能得到错误返回信息,无法正常处理。果使用了服务熔断,那么整个缓存系统的服务都被暂停了,影响的业务范围更大。而使用了请求限流机制后,整个业务系统的吞吐率会降低,能并发处理的用户请求会减少,会影响到用户体验。

所以尽量还是提前做好准备,防患于未然。


本文参考自:

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