引言😍
如今互联网开发,多用Redis作为缓存,为数据库分担访问压力。使用缓存也是设计一个高并发,高可用的系统的必备选项。
但是使用缓存也带来了一系列问题,增加了系统的复杂度和维护难度,给后端开发人员带来了不少的挑战。常见的问题有如何保证缓存与数据库数据的一致性,缓存三问题等。我们今天就来聊聊如何解决Redis的缓存三问题。
缓存雪崩
什么是缓存雪崩?😯
缓存雪崩是指在某一时间段内,大量缓存数据同时失效,导致大量请求直接打到数据库等后端存储系统上,造成后端系统压力骤增,严重时可导致系统崩溃
示意图
解决方法 (●'◡'●)
我们可以从三方面入手:
- 缓存时间:既然缓存会在某一时间段大批量的同时失效,那么我们就应该避免将大批量缓存数据的过期时间设置在同一时刻。在后台逻辑中,我们给缓存设置对应的过期时间时,应该在原有的过期时间上加上随机数,这样就可以保证数据不会大批量的在同一时间段过期
- 锁:我们知道当缓存大量失效的时候,会有大量线程来访问数据库。针对这种情况,我们可以应用锁的思想,当第一个访问对应数据的线程发现缓存已经失效,就可以拿到对应的带有过期时间的互斥锁去重建缓存,其他线程要么阻塞等待访问缓存,要么只能返回默认值。(注意:锁最好带有超时时间,防止请求发生某种意外而迟迟没有释放锁,其他线程也无法拿到锁,系统就会处于无响应的尴尬境地(╯°□°)╯︵ ┻━┻)
- 缓存不过期:既然缓存会失效,那么我们就一不做二不休,直接不给缓存设置对应的过期时间,这样缓存就不会失效了。那么如何保证缓存的时效性呢?可以由后台定时任务来更新。
每一种方案都有其优缺点,可以根据具体业务具体选择。
缓存击穿
什么是缓存击穿?😒
当某个非常频繁访问的热点key在缓存中过期时,大量的请求直接打到了数据库上,导致数据库负载骤增,这种情况被称为缓存击穿
解决方法☆*: .。. o(≧▽≦)o .。.:*☆
缓存穿透的解决方法和缓存雪崩的方法差不多
- 锁:保证在同一时刻只能有一个线程拿到重建缓存的互斥锁,其他线程要么阻塞等待访问缓存,要么只能返回默认值。
- 缓存不过期:由后台定时任务来定期异步更新缓存,缓存不设置过期时间
缓存穿透
什么是缓存穿透?😎
缓存穿透通常指的是查询一个实际上不存在于数据库中的数据,而这类请求由于在缓存中找不到对应的数据(因为它们不存在),每次都会直接穿透到数据库层。这种情况可能导致恶意攻击者利用这个漏洞发起大量无效请求,从而导致数据库过载。
解决方法(≧∇≦)ノ
- 过滤器:在访问接口前就对请求参数进行合理性判断,如果是不合理的字段或者请求参数是非法值,就直接返回对应的应答,进而保护数据库不受攻击
- 空值或者默认值:当应用上线发现有缓存穿透问题时,可以在为相应数据建立空缓存或者默认值,这样其他恶意请求也只能获取空值或者默认值,从而达到保护数据库的目的
- 布隆过滤器:当系统收到一个查询请求时,首先通过布隆过滤器检查这个查询的数据是否存在。因为布隆过滤器可以非常高效地告诉你一个元素“很可能不存在于集合中”,如果它说不存在,那么实际上就可以直接返回给用户一个空结果或错误提示,而不需要再去查询数据库。这样可以有效避免那些针对不存在数据的请求打到数据库上,从而防止缓存穿透。(注意:布隆过滤器存在误报率,当它认为数据不存在时,数据一定不存在,当它认为数据存在时,数据有可能不存在)
面试
大家在面试时,常常是不是会弄混三个概念,从而和面试官面面相觑,两个人都很尴尬🤣
笔者告诉你如何快速辨别并牢牢记住这三个概念!!
缓存雪崩:很多雪花聚集从山上一起滚落下来,这一个个雪花就是一个个缓存数据,大量缓存数据一起消失就是缓存雪崩
缓存击穿:想象一个木板,被子弹以超速击破,会形成一个点。这个空洞点,便是热点缓存消失导致的访问数据库的路径!大量请求通过这个空洞点一起访问数据库
缓存穿透:没有墙是不透风的,坏蛋会用大量的恶意请求像风一样渗透墙体,从而冲垮数据库.
笔者用形象的比喻告诉同学们这三个概念的区别了哦,是不是已经记住了呢?(笑😀) 如果有遗漏之处请指出,如果这篇文章有让你收获不少,请给笔者点赞和关注哦!这是对笔者努力更新最大的奖赏!😘