极客时间已完结课程限时免费阅读

26 | 缓存异常(下):如何解决缓存雪崩、击穿、穿透难题?

26 | 缓存异常(下):如何解决缓存雪崩、击穿、穿透难题?-极客时间

26 | 缓存异常(下):如何解决缓存雪崩、击穿、穿透难题?

讲述:蒋德钧

时长14:57大小13.66M

你好,我是蒋德钧。
上节课,我们学习了缓存和数据库的数据不一致问题和应对方法。除了数据不一致问题,我们常常还会面临缓存异常的三个问题,分别是缓存雪崩、缓存击穿和缓存穿透。这三个问题一旦发生,会导致大量的请求积压到数据库层。如果请求的并发量很大,就会导致数据库宕机或是故障,这就是很严重的生产事故了。
这节课,我就来和你聊聊这三个问题的表现、诱发原因以及解决方法。俗话说,知己知彼,百战不殆。了解了问题的成因,我们就能够在应用 Redis 缓存时,进行合理的缓存设置,以及相应的业务应用前端设置,提前做好准备。
接下来,我们就先看下缓存雪崩的问题和应对方案。

缓存雪崩

缓存雪崩是指大量的应用请求无法在 Redis 缓存中进行处理,紧接着,应用将大量请求发送到数据库层,导致数据库层的压力激增。
缓存雪崩一般是由两个原因导致的,应对方案也有所不同,我们一个个来看。
第一个原因是:缓存中有大量数据同时过期,导致大量请求无法得到处理。
具体来说,当数据保存在缓存中,并且设置了过期时间时,如果在某一个时刻,大量数据同时过期,此时,应用再访问这些数据的话,就会发生缓存缺失。紧接着,应用就会把请求发送给数据库,从数据库中读取数据。如果应用的并发请求量很大,那么数据库的压力也就很大,这会进一步影响到数据库的其他正常业务请求处理。我们来看一个简单的例子,如下图所示:
针对大量数据同时失效带来的缓存雪崩问题,我给你提供两种解决方案。
首先,我们可以避免给大量的数据设置相同的过期时间。如果业务层的确要求有些数据同时失效,你可以在用 EXPIRE 命令给每个数据设置过期时间时,给这些数据的过期时间增加一个较小的随机数(例如,随机增加 1~3 分钟),这样一来,不同数据的过期时间有所差别,但差别又不会太大,既避免了大量数据同时过期,同时也保证了这些数据基本在相近的时间失效,仍然能满足业务需求。
除了微调过期时间,我们还可以通过服务降级,来应对缓存雪崩。
所谓的服务降级,是指发生缓存雪崩时,针对不同的数据采取不同的处理方式。
当业务应用访问的是非核心数据(例如电商商品属性)时,暂时停止从缓存中查询这些数据,而是直接返回预定义信息、空值或是错误信息;
当业务应用访问的是核心数据(例如电商商品库存)时,仍然允许查询缓存,如果缓存缺失,也可以继续通过数据库读取。
这样一来,只有部分过期数据的请求会发送到数据库,数据库的压力就没有那么大了。下面这张图显示的是服务降级时数据请求的执行情况,你可以看下。
除了大量数据同时失效会导致缓存雪崩,还有一种情况也会发生缓存雪崩,那就是,Redis 缓存实例发生故障宕机了,无法处理请求,这就会导致大量请求一下子积压到数据库层,从而发生缓存雪崩。
一般来说,一个 Redis 实例可以支持数万级别的请求处理吞吐量,而单个数据库可能只能支持数千级别的请求处理吞吐量,它们两个的处理能力可能相差了近十倍。由于缓存雪崩,Redis 缓存失效,所以,数据库就可能要承受近十倍的请求压力,从而因为压力过大而崩溃。
此时,因为 Redis 实例发生了宕机,我们需要通过其他方法来应对缓存雪崩了。我给你提供两个建议。
第一个建议,是在业务系统中实现服务熔断或请求限流机制。
所谓的服务熔断,是指在发生缓存雪崩时,为了防止引发连锁的数据库雪崩,甚至是整个系统的崩溃,我们暂停业务应用对缓存系统的接口访问。再具体点说,就是业务应用调用缓存接口时,缓存客户端并不把请求发给 Redis 缓存实例,而是直接返回,等到 Redis 缓存实例重新恢复服务后,再允许应用请求发送到缓存系统。
这样一来,我们就避免了大量请求因缓存缺失,而积压到数据库系统,保证了数据库系统的正常运行。
在业务系统运行时,我们可以监测 Redis 缓存所在机器和数据库所在机器的负载指标,例如每秒请求数、CPU 利用率、内存利用率等。如果我们发现 Redis 缓存实例宕机了,而数据库所在机器的负载压力突然增加(例如每秒请求数激增),此时,就发生缓存雪崩了。大量请求被发送到数据库进行处理。我们可以启动服务熔断机制,暂停业务应用对缓存服务的访问,从而降低对数据库的访问压力,如下图所示:
服务熔断虽然可以保证数据库的正常运行,但是暂停了整个缓存系统的访问,对业务应用的影响范围大。为了尽可能减少这种影响,我们也可以进行请求限流。这里说的请求限流,就是指,我们在业务系统的请求入口前端控制每秒进入系统的请求数,避免过多的请求被发送到数据库。
我给你举个例子。假设业务系统正常运行时,请求入口前端允许每秒进入系统的请求是 1 万个,其中,9000 个请求都能在缓存系统中进行处理,只有 1000 个请求会被应用发送到数据库进行处理。
一旦发生了缓存雪崩,数据库的每秒请求数突然增加到每秒 1 万个,此时,我们就可以启动请求限流机制,在请求入口前端只允许每秒进入系统的请求数为 1000 个,再多的请求就会在入口前端被直接拒绝服务。所以,使用了请求限流,就可以避免大量并发请求压力传递到数据库层。
使用服务熔断或是请求限流机制,来应对 Redis 实例宕机导致的缓存雪崩问题,是属于“事后诸葛亮”,也就是已经发生缓存雪崩了,我们使用这两个机制,来降低雪崩对数据库和整个业务系统的影响。
我给你的第二个建议就是事前预防。
通过主从节点的方式构建 Redis 缓存高可靠集群。如果 Redis 缓存的主节点故障宕机了,从节点还可以切换成为主节点,继续提供缓存服务,避免了由于缓存实例宕机而导致的缓存雪崩问题。
缓存雪崩是发生在大量数据同时失效的场景下,而接下来我要向你介绍的缓存击穿,是发生在某个热点数据失效的场景下。和缓存雪崩相比,缓存击穿失效的数据数量要小很多,应对方法也不一样,我们来看下。

缓存击穿

缓存击穿是指,针对某个访问非常频繁的热点数据的请求,无法在缓存中进行处理,紧接着,访问该数据的大量请求,一下子都发送到了后端数据库,导致了数据库压力激增,会影响数据库处理其他请求。缓存击穿的情况,经常发生在热点数据过期失效时,如下图所示:
为了避免缓存击穿给数据库带来的激增压力,我们的解决方法也比较直接,对于访问特别频繁的热点数据,我们就不设置过期时间了。这样一来,对热点数据的访问请求,都可以在缓存中进行处理,而 Redis 数万级别的高吞吐量可以很好地应对大量的并发请求访问。
好了,到这里,你了解了缓存雪崩和缓存击穿问题,以及它们的应对方案。当发生缓存雪崩或击穿时,数据库中还是保存了应用要访问的数据。接下来,我向你介绍的缓存穿透问题,和雪崩、击穿问题不一样,缓存穿透发生时,数据也不在数据库中,这会同时给缓存和数据库带来访问压力,那该怎么办呢?我们来具体看下。

缓存穿透

缓存穿透是指要访问的数据既不在 Redis 缓存中,也不在数据库中,导致请求在访问缓存时,发生缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据。此时,应用也无法从数据库中读取数据再写入缓存,来服务后续请求,这样一来,缓存也就成了“摆设”,如果应用持续有大量请求访问数据,就会同时给缓存和数据库带来巨大压力,如下图所示:
那么,缓存穿透会发生在什么时候呢?一般来说,有两种情况。
业务层误操作:缓存中的数据和数据库中的数据被误删除了,所以缓存和数据库中都没有数据;
恶意攻击:专门访问数据库中没有的数据。
为了避免缓存穿透的影响,我来给你提供三种应对方案。
第一种方案是,缓存空值或缺省值。
一旦发生缓存穿透,我们就可以针对查询的数据,在 Redis 中缓存一个空值或是和业务层协商确定的缺省值(例如,库存的缺省值可以设为 0)。紧接着,应用发送的后续请求再进行查询时,就可以直接从 Redis 中读取空值或缺省值,返回给业务应用了,避免了把大量请求发送给数据库处理,保持了数据库的正常运行。
第二种方案是,使用布隆过滤器快速判断数据是否存在,避免从数据库中查询数据是否存在,减轻数据库压力。
我们先来看下,布隆过滤器是如何工作的。
布隆过滤器由一个初值都为 0 的 bit 数组和 N 个哈希函数组成,可以用来快速判断某个数据是否存在。当我们想标记某个数据存在时(例如,数据已被写入数据库),布隆过滤器会通过三个操作完成标记:
首先,使用 N 个哈希函数,分别计算这个数据的哈希值,得到 N 个哈希值。
然后,我们把这 N 个哈希值对 bit 数组的长度取模,得到每个哈希值在数组中的对应位置。
最后,我们把对应位置的 bit 位设置为 1,这就完成了在布隆过滤器中标记数据的操作。
如果数据不存在(例如,数据库里没有写入数据),我们也就没有用布隆过滤器标记过数据,那么,bit 数组对应 bit 位的值仍然为 0。
当需要查询某个数据时,我们就执行刚刚说的计算过程,先得到这个数据在 bit 数组中对应的 N 个位置。紧接着,我们查看 bit 数组中这 N 个位置上的 bit 值。只要这 N 个 bit 值有一个不为 1,这就表明布隆过滤器没有对该数据做过标记,所以,查询的数据一定没有在数据库中保存。为了便于你理解,我画了一张图,你可以看下。
图中布隆过滤器是一个包含 10 个 bit 位的数组,使用了 3 个哈希函数,当在布隆过滤器中标记数据 X 时,X 会被计算 3 次哈希值,并对 10 取模,取模结果分别是 1、3、7。所以,bit 数组的第 1、3、7 位被设置为 1。当应用想要查询 X 时,只要查看数组的第 1、3、7 位是否为 1,只要有一个为 0,那么,X 就肯定不在数据库中。
正是基于布隆过滤器的快速检测特性,我们可以在把数据写入数据库时,使用布隆过滤器做个标记。当缓存缺失后,应用查询数据库时,可以通过查询布隆过滤器快速判断数据是否存在。如果不存在,就不用再去数据库中查询了。这样一来,即使发生缓存穿透了,大量请求只会查询 Redis 和布隆过滤器,而不会积压到数据库,也就不会影响数据库的正常运行。布隆过滤器可以使用 Redis 实现,本身就能承担较大的并发访问压力。
最后一种方案是,在请求入口的前端进行请求检测。缓存穿透的一个原因是有大量的恶意请求访问不存在的数据,所以,一个有效的应对方案是在请求入口前端,对业务系统接收到的请求进行合法性检测,把恶意的请求(例如请求参数不合理、请求参数是非法值、请求字段不存在)直接过滤掉,不让它们访问后端缓存和数据库。这样一来,也就不会出现缓存穿透问题了。
跟缓存雪崩、缓存击穿这两类问题相比,缓存穿透的影响更大一些,希望你能重点关注一下。从预防的角度来说,我们需要避免误删除数据库和缓存中的数据;从应对角度来说,我们可以在业务系统中使用缓存空值或缺省值、使用布隆过滤器,以及进行恶意请求检测等方法。

小结

这节课,我们学习了缓存雪崩、击穿和穿透这三类异常问题。从问题成因来看,缓存雪崩和击穿主要是因为数据不在缓存中了,而缓存穿透则是因为数据既不在缓存中,也不在数据库中。所以,缓存雪崩或击穿时,一旦数据库中的数据被再次写入到缓存后,应用又可以在缓存中快速访问数据了,数据库的压力也会相应地降低下来,而缓存穿透发生时,Redis 缓存和数据库会同时持续承受请求压力。
为了方便你掌握,我把这三大问题的原因和应对方案总结到了一张表格,你可以再复习一下。
最后,我想强调一下,服务熔断、服务降级、请求限流这些方法都是属于“有损”方案,在保证数据库和整体系统稳定的同时,会对业务应用带来负面影响。例如使用服务降级时,有部分数据的请求就只能得到错误返回信息,无法正常处理。如果使用了服务熔断,那么,整个缓存系统的服务都被暂停了,影响的业务范围更大。而使用了请求限流机制后,整个业务系统的吞吐率会降低,能并发处理的用户请求会减少,会影响到用户体验。
所以,我给你的建议是,尽量使用预防式方案:
针对缓存雪崩,合理地设置数据过期时间,以及搭建高可靠缓存集群;
针对缓存击穿,在缓存访问非常频繁的热点数据时,不要设置过期时间;
针对缓存穿透,提前在入口前端实现恶意请求检测,或者规范数据库的数据删除操作,避免误删除。

每课一问

按照惯例,我给你提个小问题。在讲到缓存雪崩时,我提到,可以采用服务熔断、服务降级、请求限流的方法来应对。请你思考下,这三个机制可以用来应对缓存穿透问题吗?
欢迎在留言区写下你的思考和答案,我们一起交流讨论。如果你觉得今天的内容对你有所帮助,也欢迎你分享给你的朋友或同事。我们下节课见。
分享给需要的人,Ta购买本课程,你将得20
生成海报并分享

赞 77

提建议

上一篇
25 | 缓存异常(上):如何解决缓存和数据库的数据不一致问题?
下一篇
27 | 缓存被污染了,该怎么办?
unpreview
 写留言

精选留言(48)

  • Kaito
    2020-10-16
    是否可以采用服务熔断、服务降级、请求限流的方法来应对缓存穿透问题? 我觉得需要区分场景来看。 如果缓存穿透的原因是恶意攻击,攻击者故意访问数据库中不存在的数据。这种情况可以先使用服务熔断、服务降级、请求限流的方式,对缓存和数据库层增加保护,防止大量恶意请求把缓存和数据库压垮。在这期间可以对攻击者进行防护,例如封禁IP等操作。 如果缓存穿透的原因是,业务层误操作把数据从缓存和数据库都删除了,如果误删除的数据很少,不会导致大量请求压到数据库的情况,那么快速恢复误删的数据就好了,不需要使用服务熔断、服务降级、请求限流。如果误操作删除的数据范围比较广,导致大量请求压到数据库层,此时使用服务熔断、服务降级、请求限流的方法来应对是有帮助的,使用这些方法先把缓存和数据库保护起来,然后使用备份库快速恢复数据,在数据恢复期间,这些保护方法可以为数据库恢复提供保障。 还有一种缓存穿透的场景,我们平时会遇到的,和大家分享一下。 对于一个刚上线的新业务模块,如果还没有用户在这个模块内产生业务数据,当用户需要查询这个业务模块自己的数据时,由于缓存和数据库都没有这个用户的数据,此时也会产生缓存穿透,但这种场景不像误删数据和恶意攻击那样,而是属于正常的用户行为。 这种场景采用服务熔断、服务降级、请求限流的方式就没有任何意义了,反而会影响正常用户的访问。这种场景只能使用缓存回种空值、布隆过滤器来解决。 可见,服务熔断、服务降级、请求限流的作用是,当系统内部发生故障或潜在问题时,为了防止系统内部的问题进一步恶化,所以会采用这些方式对系统增加保护,待系统内部故障恢复后,可以依旧继续对外提供服务,这些方法属于服务治理的范畴,在任何可能导致系统故障的场景下,都可以选择性配合使用。 另外,关于文章所讲的由于“Redis缓存实例发生故障宕机”导致缓存雪崩的问题,我觉得一个可以优化的方案是,当Redis实例故障宕机后,业务请求可以直接返回错误,没必要再去请求数据库了,这样就不会导致数据库层压力变大。当然,最好的方式还是Redis部署主从集群+哨兵,主节点宕机后,哨兵可以及时把从节点提升为主,继续提供服务。 关于布隆过滤器的使用,还有几点和大家分享。 1、布隆过滤器会有误判:由于采用固定bit的数组,使用多个哈希函数映射到多个bit上,有可能会导致两个不同的值都映射到相同的一组bit上。虽然有误判,但对于业务没有影响,无非就是还存在一些穿透而已,但整体上已经过滤了大多数无效穿透请求。 2、布隆过滤器误判率和空间使用的计算:误判本质是因为哈希冲突,降低误判的方法是增加哈希函数 + 扩大整个bit数组的长度,但增加哈希函数意味着影响性能,扩大数组长度意味着空间占用变大,所以使用布隆过滤器,需要在误判率和性能、空间作一个平衡,具体的误判率是有一个计算公式可以推导出来的(比较复杂)。但我们在使用开源的布隆过滤器时比较简单,通常会提供2个参数:预估存入的数据量大小、要求的误判率,输入这些参数后,布隆过滤器会有自动计算出最佳的哈希函数数量和数组占用的空间大小,直接使用即可。 3、布隆过滤器可以放在缓存和数据库的最前面:把Redis当作布隆过滤器时(4.0提供了布隆过滤器模块,4.0以下需要引入第三方库),当用户产生业务数据写入缓存和数据库后,同时也写入布隆过滤器,之后当用户访问自己的业务数据时,先检查布隆过滤器,如果过滤器不存在,就不需要查询缓存和数据库了,可以同时降低缓存和数据库的压力。 4、Redis实现的布隆过滤器bigkey问题:Redis布隆过滤器是使用String类型实现的,存储的方式是一个bigkey,建议使用时单独部署一个实例,专门存放布隆过滤器的数据,不要和业务数据混用,否则在集群环境下,数据迁移时会导致Redis阻塞问题。
    展开
    共 26 条评论
    334
  • 徐培
    2020-10-18
    我觉得并没有必要:采用服务熔断、服务降级、请求限流的方法来应对缓存穿透的场景; 因为缓存穿透的场景实质上是因为查询到了Redis和数据库中没有的数据。 熔断、降级、限流,本质上是为了解决Redis实例没有起到缓存层作用这种情况;在损失业务吞吐量的代价下,在时间的作用下,随着过期key慢慢填充,Redis实例可以自行恢复缓存层作用。 而缓存穿透的场景,是因为用户要让Redis和数据库提供一个它没有的东西。这种场景下,如果没有人工介入,不论时间过去多久,都不太可能会自然恢复。 采用这种有损业务吞吐量的行为,会拖慢系统响应、降低用户体验、给公司一种系统“勉强能用”的错觉;但对问题的解决没有帮助。 最好的办法是事前拦截,降低这种类型的请求打到系统上的可能。布隆过滤器虽然判别数据存在可能有误判的情况,但判别数据不存在不会误判。可以降低数据库无效的访问。
    展开

    作者回复: 回答的非常好!看到了缓存穿透的本质,也看清了和击穿、雪崩情况的区别。

    共 10 条评论
    133
  • walle斌
    2020-12-24
    1)、缓存雪崩还有一个场景,是一致性hash环的集群特性导致的。集群中 某个主从节点挂掉了,请求分散到其他集群,但是量极大,把其他集群也都冲垮了。 解决办法,如果场景是热的极热 冷的极冷,不建议使用 一致性hash环的集群玩法,直接使用逻辑分组,挂掉的就暂时挂掉,后续人工恢复。 总比打垮整个系统的好 2)、缓存击穿 不只有不写过期时间,也可以对读数据做预判,例如主动给某些热的数据做 过期时间延期操作。 3)、布隆过滤器介绍 最后一部分 关于命中这部分缺少了,如果都是1 那么结果返回 存在,但是真正存在吗? 不一定,可能是由于其他value的hash函数填充的,所以 对于 布隆过滤器 返回存在的,我们要穿透到缓存与db中查询。 像一个极端情况,如果 整个bit数组 都是1 或者大部分都是1的场景,这说明什么? 说明布隆过期已经基本被填满了,也说明超出了布隆过滤器 一开始预期的大小,没错 布隆过滤器是需要事先预知 总容量大小与误判率预期的,否则就会出现 误判率极高 基本等于 没有作用的情况
    展开

    作者回复: 很赞的内容补充!谢谢。

    共 4 条评论
    48
  • 大饶Raysir
    2020-10-20
    可以记录ip和穿透访问的次数,频率超过阈值的ip直接拉黑
    15
  • 单小灰
    2020-11-03
    老师,我有个疑问,使用布隆过滤器来应对缓存穿透,那当应用刚启动的时候,布隆过滤器全是0,这样不是所有请求都会被判断为数据不存在就都直接返回了?难不成要预加载,把数据库的数据都来过滤器这边设置一遍?
    共 2 条评论
    13
  • 而立斋
    2021-04-16
    先来自己理解一下这四个问题的表现吧: 1,缓存数据与数据库数据不一致,这个就很容易理解了,就是数据出现偏差了,导致的原因是在数据变动时只更新了其中一个 2,缓存雪崩呢?缓存挂了,或者大部分key都失效了,这一下请求都打到数据库,它累了 3,缓存击穿:热点数据的失效,就像针一样同样的请求一下子刺穿了数据库的心脏 4,缓存穿透,key根本就存在无论是缓存还是数据库,但是请求一直来,这就很恶心 为什么要起 其实明白这些,一些常用的手段也就呼之欲出了。真不明白起这么多装逼的名字干嘛,不就是因为流量大了,缓存因自身限制而导致的一些现象吗?
    展开
    10
  • cp★钊
    2020-12-07
    关于穿透和雪崩,可以理解为数据的缓存命中率的不同程度的表现。雪崩代表此时命中率很低或者为0,已经到了影响DB的程度了。 同理,发生了缓存穿透,我觉得要看穿透的严重程度,可以统计命中率,在db还能抗住的情况下,可以不用熔断、降级、和限流,否则影响体验。假设命中率已经到了极限值,那这时候穿透问题上升为雪崩级别了,则可以按需要选择熔断、降级或者限流等策略

    作者回复: 穿透很多时候还是指较少的数据需要到后端DB查询,如果DB还能撑住,采取的措施可以少些。雪崩就像这个名字一样,影响范围很大了,大量的数据都失效了,都要到后端DB去查询了,会给DB带来很大压力。

    5
  • Geek3113
    2020-10-26
    布隆过滤器保护的数据只能加不能删,如果用来保护的业务数据会有删除的情况怎么办呢?
    共 3 条评论
    3
  • 寒三石
    2021-02-23
    作者提到解决缓存击穿使用手段是不给热点数据设置过期时间,但确定哪些数据是热点数据本身也是个问题,热点数据后续也有可能不再是热点数据,一直占着内存也不好
    共 2 条评论
    2
  • test
    2020-10-16
    思考题:服务熔断、服务降级、请求限流,相当于减少了数据库的压力,对于缓存穿透也是可用的。 雪崩:一批次的key同一时间失效或者redis宕机,导致同一时间有大量请求打到数据库,造成数据库很大的压力。解决方案是设置key过期时间的时候加一个随机值,或者服务熔断、服务降级、请求限流等方案; 击穿:访问非常频繁的热点数据失效,解决方案是热点数据不设置过期时间; 穿透:数据库里面没有目标数据,解决方案是布隆过滤器或者前端做验证。
    展开
    3
  • wesley
    2020-10-16
    个人理解,缓存穿透即相当于没有缓存,所有的压力都放在了数据库上。 服务熔断、服务降级、请求限流都能保证数据库的访问变少,如果是从表面上也能解决数据库的访问问题 这三种处理都是在缓存之前的、有损的且不是能自主恢复的(比如雪崩,在限流一段时间后缓存正常了就可以放开),并且降级和限流都无法避免重复且无效的查询,最后的结果可能还是服务基本不可用 所以综合来讲,个人的看法是可以用来应对,但绝对不是很好的方案
    展开
    2
  • camel
    2021-10-10
    缓存雪崩和缓存击穿有点像,都是大量请求的数据缓存里没有,对数据库造成压力。不同的是雪崩的原因是缓存大量失效,而穿透的原因是热点缓存失效。
    1
  • Heaven
    2021-08-19
    这几种方案本身就是饮鸩止渴,对于缓存穿透中可能出现的恶意攻击,是可以利用限流和熔断,降级避免应用崩溃,但是也对正常的用户体验下降了,所以还是考虑从客户请求校验这一层次考虑更好
    共 2 条评论
    1
  • 悟空聊架构
    2021-06-04
    课后题:在讲到缓存雪崩时,我提到,可以采用服务熔断、服务降级、请求限流的方法来应对。请你思考下,这三个机制可以用来应对缓存穿透问题吗? 我觉得有必要。 但是这是一种治标不治本的方案。 因为缓存穿透本质上是因为缓存和数据库都没有这个key,导致每次都要去查数据库而且还做了无效的查询,还把性能拖慢了。如果没有人工介入是没有办法恢复的。 所以要找到是哪个数据没有还被访问,然后缓存和数据库增加这个key,value为空值或缺省值。 另外还可以用布隆过滤器来判断是否没有。布隆过滤器虽然对数据“存在”有误判,对数据“不存在”是没有误判的,快速返回判断结果,就不用到数据库查询了。 还有种方案就是改前端代码了,请求这些没有的数据时做合法性校验。比如数据库中只有key=1-1000的数据,如果前端访问超过1000的key的请求,前端直接拦截这些请求。
    展开
    1
  • 编程界的小学生
    2020-12-25
    我有个缓存击穿的解决方案二,靠谱吗?如下: 分布式锁。来个请求后先锁住,然后去db查,查到后再将数据set到redis里。只有当redis里getKey没拿到数据需要请求db的时候才加锁。不影响Redis里有数据的时候处理高并发请求,也能保证db不会被打垮。
    共 1 条评论
    1
  • Andrew.Fang
    2020-12-19
    布隆过滤器怎么用你,Redis有没有命令

    作者回复: Redis的布隆过滤器是通过module进行安装的,可以下载module源码编译,然后通过下面启动方式加载这个功能 redis-server --loadmodule ./redisbloom.so 加载module后,可以用BF.ADD加入数据,BF.EXISTS判断数据是否存在。 可以参考这个链接 https://oss.redislabs.com/redisbloom/

    1
  • 孙长平  
    2022-10-06 来自北京
    老师前面讲缓存类型时候提到只读缓存,查询缓存是否存在不存在查询数据库,然后数据库存在更新到缓存。如果有数据变更或者删除动作会要求删除数据库和缓存中的数据。在缓存穿透动讲到布隆过滤器,那么只读缓存类型可以使用布隆过滤器吗,如何避免数据在缓存中不存在,在数据库中存在的情况?
  • 人如墨
    2022-09-12 来自湖北
    恶意攻击的请求是不是也可以进行黑白名单校验,判断是否让其进行查询
  • Geek_b14c55
    2022-09-06 来自浙江
    请求限流是可以实现解决缓存穿透的,服务降级和熔断也可以解决,但是服务降级和熔断更多指的是服务不可用,缓存穿透在没有打挂掉数据库时,是没有这个问题的。
  • 菜鸟葫芦娃
    2022-07-05
    随着时间点推移,布隆过滤器会有短暂的浪费空间,哪些空间如何再利用呢?