一、 缓存雪崩
起因:
- 大部分key设置缓存失效时间都相同,同时失效,大量请求无法处理
- Redis缓存实例发生故障宕机,无法处理请求,大量请求就会发送到数据库层
- 更新策略存在问题
- 数据热点
解决方案:
①缓存时间尽可能不设置相同失效时间,可在时间上加上随机数,缓存时间的重复率就会变低
②Redis高可用集群方案 ,主从+哨兵~ 参考Redis Cluster部署集群方案
③通过服务降级比如Hystrix去应对缓存雪崩 ,针对非核心数据,暂停从缓存中获取这些数据,直接返回预定义消息或者错误信息
④重点来了:联系运维赶紧修复redis问题
二、缓存穿透
起因:
大量并发查询不存在的KEY,缓存中和数据库都没有,导致直接将压力透传到数据库。
举个例子:
访问id=-1的数据,缓存中没有去数据库中查肯定也没有,并发查询压力直接来到了数据库
解决方案:
①缓存空对象(不建议)
缓存空对象,下次同样请求就会命中这个空对象,缓存层就处理了这个请求,不会对数据库产生压力
②布隆过滤器
将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
当布隆过滤器说某个值存在时,这个值可能不存在;当它说不存在时,那就肯定不存在。
guava布隆过滤器基于内存实现,不适合分布式环境~ 可用redis自己实现布隆过滤器
三、缓存击穿
起因:
缓存击穿是指请求要访问的数据,缓存中没有,但数据库中有。
(通常都为热点key 失效时,正好有大量并发请求访问该KEY)
解决方案:
①互斥锁
互斥锁方案的思路就是如果从redis中没有获取到数据,就让一个线程去数据库查询数据,然后构建缓存,其他的线程就等着,过一段时间后再从redis中去获取。
相关原理就是在缓存失效时,不会立即去数据库查询,使用缓存工具的某些带成功操作返回值的操作如:
Redis setnx
基于redission local()方法 实现互斥锁 ~
②XXL-JOB
后台写个定时任务专门主动更新即将过期的数据,强行续命~
③永生法
既然是热点key 干脆不过期了~ 简单粗暴,就不整那些幺蛾子了
具体方案可根据实际业务结合多种方案保证程序正常运行