一般情况下Redis用于减轻请求对数据库的压力,所以一旦redis缓存出现雪崩、穿透、击穿情况,此时请求会直接请求数据库,大量的请求就可能导致数据库响应超时甚至崩溃,所以应该尽量防止redis出现以上情况。
一、缓存穿透:
关键词:绕过Redis直接访问DB
Redis作为缓存一般使用方式,先去 Redis 中查找某资源,Redis 中查不到就去 DB 中查,DB 中查到后回写一份数据到 Redis 中;非正常情况下有用户恶意重复请求资源A,该资源在 Redis 和 DB 中都不存在。那么每次请求都会直接打到 DB 上,增加DB压力。
解决方案:
1、缓存空结果
当Redis 及 DB 中都不存在该资源,就缓存空结果一段时间,一定要设置一个较短的缓存失效时间,防止数据库数据更新后,请求依然返回缓存的情况。
2、用户合法性校验
对用户的请求合法性进行校验,拦截恶意重复请求。
3、布隆过滤器
此文作者介绍的非常详细:
布隆过滤器究竟是什么,这一篇给讲的明明白白的
二、缓存击穿
关键词:针对某key定点打击
试想如果所有请求对着一个 key 照死里搞,这是不是就是一种定点打击呢?
怎么理解呢?举个极端的例子:比如某某明星爆出一个惊天狠料,海量吃瓜群众同时访问微博去查看该八卦新闻,而微博 Redis 集群中数据在此刻正好过期了,那么无数的请求则直接打到了微博系统的物理 DB 上,DB 瞬间挂了。
解决方案:
1、热点数据永远不过期
比如我们可以将某个 key 的缓存时间设置为 25 小时,然后后台有个 JOB 每隔 24 小时就去批量刷新一下热点数据。
2、使用互斥锁
容易影响吞吐量,大部分项目设置热点 key 永不过期就妥妥的了。
三、缓存雪崩
关键词:热点key同时过期
Redis集群中的热点 key 在某一时刻同时失效,海量请求直接请求 DB,DB可能在瞬间就被打爆了。
解决方案:
1、Redis 失效时间加上随机数
Redis 失效时间加上随机数,是一种比较取巧的解决方案。在一定程度上减轻了 DB 的瞬时压力,但是这种方案也在一定程度上增加了维护的成本。
2、Redis 永不过期
实现见上文。
参考资料:
https://juejin.cn/post/6880752890416529416
https://juejin.cn/post/7027440894378770439