【后端面经】【缓存】35|缓存问题:怎么解决缓存穿透、击穿和雪崩问题?---解决缓存穿透

简介: 【5月更文挑战第14天】解决缓存穿透问题有两种策略。一是回写特殊值,当数据不存在时,在缓存中存储特殊值以标记,避免下次重复查询数据库。但此方法可能被恶意请求利用,浪费内存。二是使用布隆过滤器,预先判断数据是否存在,减少无效数据库查询。布隆过滤器虽有假阳性可能,但概率低,可接受。此外,可先查缓存再查布隆过滤器,优化正常请求的效率。两种方式各有优劣,实际应用需根据场景选择。

解决缓存穿透

缓存穿透是因为数据本身不存在而引起的,所以我们就要想办法在确认数据不存在之后,避免下一次查询再次落到数据库上。这里有两种解决思路。

回写特殊值

第一种思路是在缓存未命中,而且数据库也没有的情况下,往缓存里写入一个特殊的值。这个值就是标记数据不存在。那么下一次查询请求过来的时候,看到这个特殊值,就知道没有必要再去数据库查询了。
2024-05-15-21-43-26-image.png

你可以直接介绍这个方案

第一种思路是回写特殊值,也就是在第一次查询发现数据里都没有数据的时候,直接写入一个特殊值。那么下一次查询过来的时候,看到缓存里的特殊值,就知道没有数据,这时候直接返回就可以了。在这种设计下,数据库只需要支撑住第一次请求就可以。

但是这个方案也是有缺点的。

如果攻击者每次都用不同且不存在的key来请求数据,那么这种措施毫无效果。并且,因为要回写特殊值,那么这些不存在的key都会有特殊值,浪费了Redis的内存。这可能会进一步引起另外一个问题,就是Redis在内存不足,执行淘汰的时候,把其他有用的数据淘汰掉。

这个时候可以引出下一个点了,考虑使用布隆过滤器。

布隆过滤器

既然缓存穿透是因为数据不存在,那么提前用布隆过滤器判断一下不就可以了吗。

正常请求一个key的流程如下:
2024-05-15-21-49-38-image.png

如果请求一个 key 不存在,那么布隆过滤器会直接说数据不存在,那么就没必要继续往下查询了。
2024-05-15-21-49-48-image.png

首先简单介绍这个流程

使用布隆过滤器的流程是业务代码收到请求之后,要先问一下布隆过滤器有没有这个key。如果说没有,就不用继续往后执行了。如果布隆过滤器说有,那么就继续往后执行,去查询缓存和数据库,并且查询到了数据的时候,回写到缓存里面。

然后你要记得介绍假阳性的问题。

但是布隆过滤器本身存在假阳性的问题,所以当攻击者请求一个不存在的key的时候,布隆过滤器可能会返回数据存在的假阳性响应。在这种情况下,业务代码依旧会去查询缓存和数据库。不过因为假阳性的概率很低,如果说概率是万分之一,就算攻击的并发有百万,也只有100个查询请求会落到数据库上。

这个时候可以补充一个变种

也可以考虑先查询缓存,当缓存中没有数据的时候,再去查询布隆过滤器。如果布隆过滤器说有数据,再去查询数据库。
2024-05-15-21-59-29-image.png

然后你对比两者。

这两种模式没有太大的差别。先查询布隆过滤器,保护效果会更好,也就是提前挡住了非法请求。而先查询缓存,对正常请求更加友好,因为正常请求大概率命中缓存,直接返回数据,也就不用查询布隆过滤器了。

不过如果布隆过滤器也是在 Redis 的基础上实现的,两者就基本上没什么区别了。

目录
相关文章
|
20天前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
这篇文章是关于如何在SpringBoot应用中整合Redis并处理分布式场景下的缓存问题,包括缓存穿透、缓存雪崩和缓存击穿。文章详细讨论了在分布式情况下如何添加分布式锁来解决缓存击穿问题,提供了加锁和解锁的实现过程,并展示了使用JMeter进行压力测试来验证锁机制有效性的方法。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解分布式情况下如何添加分布式锁 【续篇】
|
20天前
|
缓存 NoSQL Java
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
这篇文章介绍了如何在SpringBoot项目中整合Redis,并探讨了缓存穿透、缓存雪崩和缓存击穿的问题以及解决方法。文章还提供了解决缓存击穿问题的加锁示例代码,包括存在问题和问题解决后的版本,并指出了本地锁在分布式情况下的局限性,引出了分布式锁的概念。
SpringBoot整合Redis、以及缓存穿透、缓存雪崩、缓存击穿的理解、如何添加锁解决缓存击穿问题?分布式情况下如何添加分布式锁
|
16天前
|
缓存 网络协议 API
【API管理 APIM】APIM中对后端API服务的DNS域名缓存问题
【API管理 APIM】APIM中对后端API服务的DNS域名缓存问题
|
21天前
|
缓存 数据库
缓存穿透和击穿
【8月更文挑战第16天】
32 0
缓存穿透和击穿
|
24天前
|
缓存 NoSQL Redis
一天五道Java面试题----第九天(简述MySQL中索引类型对数据库的性能的影响--------->缓存雪崩、缓存穿透、缓存击穿)
这篇文章是关于Java面试中可能会遇到的五个问题,包括MySQL索引类型及其对数据库性能的影响、Redis的RDB和AOF持久化机制、Redis的过期键删除策略、Redis的单线程模型为何高效,以及缓存雪崩、缓存穿透和缓存击穿的概念及其解决方案。
|
12天前
|
存储 缓存 关系型数据库
Django后端架构开发:缓存机制,接口缓存、文件缓存、数据库缓存与Memcached缓存
Django后端架构开发:缓存机制,接口缓存、文件缓存、数据库缓存与Memcached缓存
25 0
|
12天前
|
存储 缓存 数据库
Django后端架构开发:信号与缓存架构开发
Django后端架构开发:信号与缓存架构开发
52 0
|
23天前
|
存储 缓存 NoSQL
基于SpringBoot+Redis解决缓存与数据库一致性、缓存穿透、缓存雪崩、缓存击穿问题
这篇文章讨论了在使用SpringBoot和Redis时如何解决缓存与数据库一致性问题、缓存穿透、缓存雪崩和缓存击穿问题,并提供了相应的解决策略和示例代码。
51 0
|
13天前
|
缓存 NoSQL Redis
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
【Azure Redis 缓存】Redission客户端连接Azure:客户端出现 Unable to send PING command over channel
|
10天前
|
缓存 NoSQL Java
Redis深度解析:解锁高性能缓存的终极武器,让你的应用飞起来
【8月更文挑战第29天】本文从基本概念入手,通过实战示例、原理解析和高级使用技巧,全面讲解Redis这一高性能键值对数据库。Redis基于内存存储,支持多种数据结构,如字符串、列表和哈希表等,常用于数据库、缓存及消息队列。文中详细介绍了如何在Spring Boot项目中集成Redis,并展示了其工作原理、缓存实现方法及高级特性,如事务、发布/订阅、Lua脚本和集群等,帮助读者从入门到精通Redis,大幅提升应用性能与可扩展性。
24 0
下一篇
DDNS