一次分清缓存穿透,缓存击穿,缓存雪崩

本文涉及的产品
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Redis 版,经济版 1GB 1个月
简介: 如果数据库查询压力过大怎么办?当然是上缓存了。似乎缓存就是为了缓解数据库压力而生,那就这样完了吗?自然不是,可曾遇到过面试Redis的时候经常被问什么是缓存穿透,缓存击穿,这两者有什么区别?啊,真是头大,一字之差。今天小马就来一起探讨下这一块呀。

Redis为什么快

Redis采用的是基于内存的单线程模型的key/value数据库,由C语言编写,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。单线程为什么这么快?主要还是得益于基于内存,哈希数据结构和单线程上。以下引用一段总结来解释。

1、完全基于内存,绝大部分请求是纯粹的内存操作,数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1);

2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

4、使用多路I/O复用模型,非阻塞IO。“多路”指的是多个网络连接,“复用”指的是复用同一个线程;

5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

缓存穿透

啊,查了一下百度百科,似乎没有相关的解释,那只能自己来了。缓存穿透就是如果请求带着id过来了,像查询id=-1的数据,于是缓存里自然没有该数据,因为数据库本来也就没有该数据。那这个就有趣了,如果不断大量恶意请求,那就是直接绕过缓存,一直在查数据库,给数据库造成极大的压力,这就是缓存穿透。

有了问题自然就要想法子解决,提供参考如下:

1、在逻辑代码处做一层请求校验,例如,id的请求范围校验。如果请求的参数不符合规矩那就直接拒绝请求了,连缓存都拒绝请求了更别说请求到数据库了;

2、尽量坏数据也做缓存。比如恶意请求的参数缓存和数据库库都获取不到数据一次就直接缓存为坏数据一段时间(比如有一个缓存池key都为bad_id系列,id请求过来后先查询key=bad_id系列是否有数据,没有的话再请求key=id的缓存数据),这样就可以缓解恶意请求带来的压力;

3、那如果不是恶意请求,比如正常id=1的请求,此时刚好缓存没数据,数据库也查不到数据时,也是建议缓存处理,如处理为key=>null。但这个缓存时间要根据实际业务情况设置,不宜过长,比如30秒,否则会影响正常情况的获取(比如缓存为null期间数据库已经有写入相关参数的数据了,此时就出问题了)。

4、布隆过滤器。可以使用布隆过滤器解决缓存穿透的问题,把已存在数据的key存在布隆过滤器中。当有新的请求时,先到布隆过滤器中查询是否存在,如果不存在该条数据直接返回;如果存在该条数据再查询缓存查询数据库。这个等下详细讨论,通俗理解为,当布隆过滤器说,某种东西存在时,这种东西可能不存在;当布隆过滤器说,某种东西不存在时,那么这种东西一定不存在。比如布隆还用在了识别垃圾邮箱的功能上。

缓存击穿

缓存击穿就是当请求参数过来,缓存中的数据瞬间过期,此时并发量又大,全部请求直接同时转为去请求数据库,瞬间给数据库带来巨大压力。

参考的解决方案自然也有:

1、设置热点数据永远不过期。这个法子最为粗暴了。

2、加互斥锁。就是同一时间只能有一个请求去查询DB更新缓存。然后其他请求再从缓存中取数据。代码实现就是,对缓存过期后去请求数据库的操作加互斥锁,其他获取不到锁的请求直接等待(sleep)数秒后再去重新请求获取数据的方法,自然就能从缓存取数据了,真是智慧。

3、将同一热点数据均匀分布在不同的缓存节点中(比如将key哈希分散存储,如id_hash(openid),单独设置过期时间),这样即可分散热key对redis的压力也可避免同一时间过期后大量请求一起同时涌向数据库查询数据。

缓存穿透和击穿的区别

这两者的区别上面已经很清晰了,总结一下,穿透就缓存无数据数据库也无数据,击穿就是缓存无数据数据库有数据。穿透一般是攻击行为导致,击穿很可能就是缓存处理不当导致。透为无则通透,击为有则击之。无则通透,有则击之,哈哈,这是小马的口诀。

缓存雪崩

啊,刚理清击穿和穿透,又来一个雪崩,真是头大。引用别人的一段话来解释,小马觉得概括得很是精辟易懂。

缓存雪崩是指缓存中数据大批量同时到过期时间(比如redis服务突然挂了后重启),而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
image.png

解决方案建议:

1、设置热点数据永远不过期;

2、缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生,就是将缓存过期时间设置错开;

3、将热点数据均匀分布在不同的缓存节点中,这样即可防止热点压力,又可以防止缓存同一时间过期,导致雪崩。这点和击穿的预防方法异曲同工。

关于缓存击穿,缓存穿透,缓存雪崩就到这里了。值得一提的是,布隆过滤器是个一种比较巧妙的概率型数据结构,它可以告诉你某种东西一定不存在或者可能存在,比较有趣,这点有时间要细细起个篇幅探讨下。谢谢品阅。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
9天前
|
缓存 NoSQL Java
避免缓存失效的三大杀手:缓存击穿、穿透与雪崩的解决方案
避免缓存失效的三大杀手:缓存击穿、穿透与雪崩的解决方案
17 0
|
2月前
|
缓存 监控 NoSQL
redis 缓存穿透 击穿 雪崩 的原因及解决方法
redis 缓存穿透 击穿 雪崩 的原因及解决方法
|
28天前
|
存储 缓存 NoSQL
应对危机如何处理缓存击穿风险
【6月更文挑战第9天】本文介绍如何应对缓存穿透,这可以通过限制IP访问次数、预热缓存、设置空值以及使用布隆过滤器来过滤非法请求。布隆过滤器占用空间小,有误判率但速度快,适用于广告投放、内容推荐和数据库查询等场景。其优点包括低时间复杂度、并行运算和节省空间,但存在误判、无法存储元素及删除操作的局限性。
33 4
应对危机如何处理缓存击穿风险
|
11天前
|
存储 缓存 监控
详解缓存雪崩、缓存击穿、缓存穿透问题,一文掌握,干货不断
详解缓存雪崩、缓存击穿、缓存穿透问题,一文掌握,干货不断
|
2月前
|
缓存 数据库 NoSQL
【后端面经】【缓存】35|缓存问题:怎么解决缓存穿透、击穿和雪崩问题?--主从切换方案
【5月更文挑战第16天】该方案提出了解决Redis缓存穿透、击穿和雪崩问题的策略。通过使用两个或多个互为备份的Redis集群,确保在单个集群故障时,另一个可以接管。在故障发生时,业务会与备用集群保持心跳检测,并根据业务重要性分批转移流量,逐步增加对备用集群的依赖,同时监控系统稳定性。对于成本敏感的小型公司,可以采用低成本的单机或小规模自建Redis备份。此方案强调渐进式流量转移,以保护系统免受突然压力冲击。
31 1
【后端面经】【缓存】35|缓存问题:怎么解决缓存穿透、击穿和雪崩问题?--主从切换方案
|
9天前
|
缓存 NoSQL Java
Redis系列学习文章分享---第四篇(Redis快速入门之Java客户端--商户查询缓存+更新+双写一致+穿透+雪崩+击穿+工具封装)
Redis系列学习文章分享---第四篇(Redis快速入门之Java客户端--商户查询缓存+更新+双写一致+穿透+雪崩+击穿+工具封装)
13 0
|
2月前
|
存储 缓存 NoSQL
【后端面经】【缓存】35|缓存问题:怎么解决缓存穿透、击穿和雪崩问题?---解决缓存穿透
【5月更文挑战第14天】解决缓存穿透问题有两种策略。一是回写特殊值,当数据不存在时,在缓存中存储特殊值以标记,避免下次重复查询数据库。但此方法可能被恶意请求利用,浪费内存。二是使用布隆过滤器,预先判断数据是否存在,减少无效数据库查询。布隆过滤器虽有假阳性可能,但概率低,可接受。此外,可先查缓存再查布隆过滤器,优化正常请求的效率。两种方式各有优劣,实际应用需根据场景选择。
30 3
|
2月前
|
缓存 数据库 算法
【后端面经】【缓存】35|缓存问题:怎么解决缓存穿透、击穿和雪崩问题?---解决缓存击穿和雪崩、限流
【5月更文挑战第15天】本文介绍了如何解决缓存击穿和雪崩问题。对于缓存击穿,采用singleflight模式,确保即使热点数据导致大量请求未命中缓存,也只允许一个请求真正查询数据,其他请求等待其结果。对于缓存雪崩,解决方案是在设置过期时间时添加随机偏移量,避免所有数据同时过期。偏移量应与过期时间成正比。此外,限流也是一个重要策略,可以在服务层和数据库层实施,以限制请求流量,保护数据库免受高并发压力。
28 0
【后端面经】【缓存】35|缓存问题:怎么解决缓存穿透、击穿和雪崩问题?---解决缓存击穿和雪崩、限流
|
12天前
|
存储 缓存 NoSQL
redis缓存优化
采用获取一次缓存,如果为空的情况,获取分布式锁,让一个线程去重建缓存,另外的线程未获取到锁的情况,休眠短时间,然后再自旋获取缓存。
19 0
|
17天前
|
缓存 NoSQL Java
在 Spring Boot 应用中使用 Spring Cache 和 Redis 实现数据查询的缓存功能
在 Spring Boot 应用中使用 Spring Cache 和 Redis 实现数据查询的缓存功能
36 0