1.缓存穿透
概念:
用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多时,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
解决方案:
1.布隆过滤器
布隆过滤器(Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。
布隆过滤器会在我的另一篇博客中详细解释
2.缓存空对象
当存储层不命中后,即使返回的空对象也将其缓存起来,同时设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源
但是缓存空对象会存在下列问题:
1.空值被缓存起来,会占用更多的空间
2.即使设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致这对 需要保持一致性的业务会有影响
2.缓存击穿
概念:
一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,并且回写缓存,会导致数据库瞬间压力过大
解决方案:
1.设置热点数据永不过期
2.加互斥锁
分布式锁:使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有
获得分布式锁的权限,因此只需要等待即可,但是对分布式锁的考验很大
3.缓存雪崩
概念:
某一时间段,缓存集中过期失效/redis宕机/断网
解决方案:
1.redis高可用
多设几台redis
2.限流降级
缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量
3.数据预热
在正式部署之前,我先把可能的数据访问一边,这样部分可能大量访问的数据就会
加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的
过期时间,让缓存失效的时间尽量均匀