redis的穿透、击穿、雪崩有什么不同点?

赏金任务每周更新,请持续关注哦 :love_letter:

题目

  • 模拟面试场景,面试官提问以下问题,你如何回答。
  • redis的穿透、击穿、雪崩有什么不同点?

参与方式

  • 本帖下方回复你的答案即可

赏金

  • 100元京东购物卡

活动时间

  • 2023年4月24日 - 2023年4月30日

本周赏金任务汇总: 🌈 赏金任务发布 2023-04-10

本问题参与赏金活动,详情点击 :rainbow: 赏金活动上线啦 丨做赏金任务挑战千元奖金 查看活动介绍

Redis的穿透、击穿、雪崩是三种不同的缓存问题,具体区别如下:

  1. 穿透:指查询一个缓存中不存在的数据,导致每次请求都需要查询数据库,造成数据库压力过大。
  2. 击穿:指查询一个缓存中存在的但是即将过期的数据,此时大量请求同时到来,导致缓存失效,每次请求都需要查询数据库,造成数据库压力过大。
  3. 雪崩:指大量缓存数据同时失效,导致大量请求同时到来,每次请求都需要查询数据库,造成数据库压力过大。
    综上所述,三种问题的区别在于缓存中数据的存在状态和失效情况,而造成的后果都是需要查询数据库,导致数据库压力过大。因此,解决这些问题的方法都是通过合理的缓存策略和技术手段来避免缓存失效。

前言

作为一种非关系型数据库,redis也总是免不了有各种各样的问题。如何有效的理解并且区分 Reids 穿透、击穿和雪崩之间的区别,一直以来都挺困扰我的一个难题,下面将一一举例。

(一)缓存穿透

关键词:穿过 Redis 和数据库

当 Redis 和数据库中都没有我们想要的数据时,就需要考虑缓存穿透的问题了。下面这段逻辑大家用的会比较多:先去 Redis 中查找某资源,Redis 中查不到就去 DB 中查,DB 中查到后回写一份数据到 Redis 中。

举例

对于系统A,假设一秒 5000 个请求,结果其中 4000 个请求是黑客发出的恶意攻击。
黑客发出的那 4000 个攻击,缓存中查不到,每次你去数据库里查,也查不到。
数据库 id 是从 1 开始的,结果黑客发过来的请求 id 全部都是负数。这样的话,缓存中不会有,请求每次都“视缓存于无物”,直接查询数据库。这种恶意攻击场景的缓存穿透就会直接把数据库给打死。

解决方案

1、缓存空结果

如果系统发现 Redis 及 DB 中都不存在该资源,就缓存空结果一段时间。需要注意哈,这次的失效时间不能设置的太长,否则数据的实效性会产生很大的问题。

2、用户合法性校验

对用户的请求合法性进行校验,拦截恶意重复请求。

3、布隆过滤器

看到这个名词不要慌。简单来说布隆过滤器的用途就是帮助你判断某个值是否存在。举个例子来看下:假设我们现在有一个长度为 9 的 bit 数组,该数组的每个位置上只能保存 1 或者 0,1 标识该位置被占用,0 标识该位置未被使用。

对于 key1,我们借助三个 Hash 函数分别对其哈希运算。

再将得到的这三个哈希值对 9 求模。

最后将这三个模值落入到 bit 数组上。

key2、key3 按照同样的方式再处理一遍。

最后,我们会发现这个 bit 数组里只有位置 3 还是空着的。如果此时来了一个新的 key4 通过三个Hash算法求出的哈希值为 1、2、3,我们则可以断定 key4 一定不存在。

布隆过滤器的原理还是比较简单的。这里我们需要注意,布隆过滤器可能存在一定误判的可能性,但它依然可以帮助你拦截掉大部分一定不存在的数据。

(二)缓存击穿

关键词:定点打击

试想如果所有请求对着一个 key 照死里搞,这是不是就是一种定点打击呢?

举例

怎么理解呢?举个极端的例子:比如某某明星爆出一个惊天狠料,海量吃瓜群众同时访问微博去查看该八卦新闻,而微博 Redis 集群中数据在此刻正好过期了,那么无数的请求则直接打到了微博系统的物理 DB 上,DB 瞬间挂了。

解决方案

1、热点数据永远不过期

比如我们可以将某个 key 的缓存时间设置为 25 小时,然后后台有个 JOB 每隔 24 小时就去批量刷新一下热点数据。就可以解决这个问题了。

2、使用互斥锁

容易影响吞吐量,大部分项目设置热点 key 永不过期就妥妥的了。

(三)缓存雪崩

关键词:Redis 崩了,没有数据了

这里的 Redis 崩了指的并不是 Redis 集群宕机了。而是说在某个时刻 Redis 集群中的热点 key 都失效了。如果集群中的热点 key 在某一时刻同时失效了的话,试想海量的请求都将直接打到 DB 上,DB 可能在瞬间就被打爆了。

举例

对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机。缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据库必然扛不住,它会报一下警,然后就挂了。此时,如果没有采用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。

解决方案:

1、事前

事前:redis 高可用,主从+哨兵,redis cluster,避免全盘崩溃。

2、事中

事中:本地 ehcache 缓存 + hystrix 限流&降级,避免 MySQL 被打死。

3、事后

事后:redis 持久化,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据。

(四)简短易懂总结

最后我们再回归到主题!如何轻松的通过联想的方式来区分 Redis 缓存穿透、击穿、雪崩的区别?

缓存穿透—穿过(绕过) Redis 和 DB 来搞你

缓存击穿—定点打击来搞你

缓存雪崩—热点 key 在某一个时刻同时失效

Redis的穿透、击穿、雪崩是三种不同的缓存问题,它们的发生原因和解决方法也不同。

  1. 穿透

穿透是指查询一个不存在的数据,由于缓存中没有数据,所以每次查询都要去数据库中查询,这样会导致数据库的压力过大。攻击者可以通过构造恶意请求,来反复查询不存在的数据,从而使数据库宕机。

解决方法:

  • 在缓存中添加空对象或默认值,避免重复查询。
  • 对查询参数进行校验,过滤掉非法请求。
  • 设置布隆过滤器,过滤掉不存在的数据。
  1. 击穿

击穿是指查询一个存在的数据,由于某些原因(如缓存的过期时间到了),缓存中没有数据,这样会导致每次查询都要去数据库中查询,从而导致数据库的压力过大。

解决方法:

  • 在查询时,先查缓存,如果缓存不存在,则查询数据库,并将查询结果写入缓存。
  • 设置热点数据不过期,或者设置较长的过期时间。
  1. 雪崩

雪崩是指在某个时间段,缓存集中过期失效,导致大量的请求都落到数据库上,从而导致数据库的压力过大,甚至宕机。

解决方法:

  • 使用分布式锁,避免缓存失效时大量的请求同时访问数据库。
  • 对缓存的过期时间进行随机化,避免缓存集中过期。
  • 使用多级缓存,将请求分散到不同的缓存中,避免缓存同时失效。

总之,穿透、击穿、雪崩是Redis常见的三种缓存问题,它们的发生原因和解决方法也不同。在使用Redis时,需要注意缓存的设置和管理,以避免这些问题的发生。

主要这三种问题主要都会导致请求直接落到数据库上,增加了数据库的负担,影响系统的性能和稳定性。

不同点是:穿透是查询不存在的数据,击穿是热点数据过期或删除,雪崩是缓存大量数据同时失效。

相同点是:都是由于缓存失效或者不存在而导致的。

触发方式:穿透通过恶意请求触发,击穿和雪崩通常是由于缓存服务器宕机、缓存失效时间设置不当等原因触发。

再让我们来了解一下这些问题的定义和解决方案:

1. 穿透(Cache Penetration):
穿透指查询一个不存在的数据,由于缓存中没有该数据,每次查询都会落到数据库上,导致数据库压力过大。通常是攻击者通过构造恶意请求来访问不存在的key,使得缓存失效,请求直接访问数据库。
解决方案包括:布隆过滤器、在缓存中保存空对象或默认值,这样当请求再次到达时就可以直接返回空值,而不必再次访问数据库。。

2. 击穿(Cache Breakdown):
击穿指某个热点数据过期或被删除,而此时又有大量并发请求访问该数据,这些请求会直接落到数据库上,导致数据库压力过大。
解决方案包括:热点数据永不过期、加锁避免并发读写、使用分布式锁等。

3. 雪崩(Cache Avalanche):
雪崩指缓存中的大量数据同时失效,导致所有请求都直接落到数据库上,导致数据库压力过大甚至宕机。通常是由于缓存服务器挂掉、缓存服务器重启或者大量key同时过期导致。
解决方案包括:缓存失效时间加上随机值、多级缓存架构、缓存预热等。

除了以上几种策略外,还有一些其他的注意事项可以帮助我们避免Redis的穿透、击穿和雪崩问题。例如:我们可以采用缓存预热、限流等技术来降低系统负载;我们还可以对缓存数据进行合理的分片和压缩,以提高系统性能和可靠性。

在使用Redis缓存系统时,我们需要注意这些常见问题,并采取相应的措施来避免它们的发生。通过合理的缓存策略和技术手段,我们可以提高系统性能和可靠性,为用户提供更好的体验。

Redis是一种常用的内存缓存系统,常常用于加速数据访问。但是,如果在使用Redis时不考虑某些情况,可能会出现穿透、击穿、雪崩等问题,导致缓存系统的性能下降或崩溃。以下是对这三种问题的解释和使用场景的总结:

问题 描述 使用场景
穿透 当一个查询请求无法从缓存中获取到数据,因为数据不存在,导致请求直接访问底层数据存储系统。这将导致大量的请求被发送到存储系统,导致存储系统过载。 当缓存中没有请求的数据时,请求访问缓存。
击穿 当某个键非常热门,但是由于某种原因(例如过期)被删除,导致所有请求都穿透到存储系统。 当一个缓存键在一段时间内非常热门,但是在过期后被删除时,请求访问该键。
雪崩 当缓存中的一组键由于某种原因(例如过期)同时失效,并且所有请求都穿透到存储系统,导致存储系统过载。 当大量的缓存键同时过期时,请求访问这些键。

在下表中,我们总结了这三种问题的区别和相应的解决方案:

问题 描述 解决方案
穿透 缓存中缺少所需数据 1. 在缓存中添加空值,以便下次访问时缓存查询返回一个空结果
2. 在查询请求到达缓存之前进行数据验证
击穿 热门数据被删除 1. 使用锁机制,以便在缓存未准备好数据之前,其他请求不能删除它
2. 使过期时间分散,不要所有的缓存键同时过期
雪崩 大量缓存键同时过期 1. 在设置缓存键时添加随机过期时间,以避免大量缓存键同时过期
2. 使用多个缓存层级,以便在某个缓存层级失效时,请求可以访问其他缓存层级