1. 缓存穿透【不要相信对方。不要相信任何第三方】
指查询一个一定不存在的数据,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到 DB 去查询,可能导致 DB 挂掉。
解决方案:【接口层增加校验和签名,比如用户鉴权校验,参数做校验,不合法的参数直接代码Return,比如:id 做基础校验,id <=0的直接拦截等。】
i. 查询返回的数据为空,仍把这个空结果进行缓存,但过期时间会比较短
ii. 布隆过滤器:将所有可能存在的数据哈希到一个足够大的 bitmap 中,一个一定不存在的数据会被这个 bitmap 拦截掉,从而避免了对 DB 的查询。
iii. Nginx可以有针对ip的每秒请求次数的相关配置
2. 缓存击穿
缓存击穿
是指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。
解决方案:
i. 使用互斥锁:当缓存失效时,不立即去 load db,先使用如 Redis 的 setnx 去设置一个互斥锁,当操作成功返回时再进行 load db 的操作并回设缓存,否则重试 get 缓存的方法。
ii 永远不过期:物理不过期,但逻辑过期(后台异步线程去刷新)
3. 缓存雪崩【因为大面积的缓存失效,打崩了DB】
同一时间大面积失效,那一瞬间Redis跟没有一样,那这个数量级别的请求直接打到数据库几乎是灾难性的
举个简单的例子:如果所有首页的Key失效时间都是12小时,中午12点刷新的,我零点有个秒杀活动大量用户涌入,假设当时每秒 6000 个请求,本来缓存在可以扛住每秒 5000 个请求,但是缓存当时所有的Key都失效了。此时 1 秒 6000 个请求全部落数据库,数据库必然扛不住,它会报一下警,真实情况可能DBA都没反应过来就直接挂了。此时,如果没用什么特别的方案来处理这个故障,DBA 很着急,重启数据库,但是数据库立马又被新的流量给打死了。这就是我理解的缓存雪崩。
解决:
在批量往
Redis
存数据的时候,把每个Key的失效时间都加个随机值就好了
4. 总结
一般避免以上情况发生我们从三个时间段去分析下:
事前:Redis 高可用,主从+哨兵,Redis cluster,避免全盘崩溃。
事中:本地 Guava 缓存 + Sentinel 限流+降级,避免MySQL 被打死。
事后:Redis 持久化 RDB+AOF,一旦重启,自动从磁盘上加载数据,快速恢复缓存数据
5. 布隆过滤器
布隆过滤器究竟是什么,这一篇给讲的明明白白的_vincent-CSDN博客_什么是布隆过滤器
也就是说:来源是位图+哈希。 [为了时间和空间更加平衡一点,引入了布隆过滤器]
如果布隆过滤器判断元素在集合中存在,不一定存在
如果布隆过滤器判断不存在,一定不存在