Redis缓存穿透和雪崩(面试高频,工作常用)
缓存穿透(查不到导致的)
概念
用户想要查询一个数据,发现Redis中没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求持久层数据库,这就给持久层数据库造成很大的压力,这就是缓存穿透。
解决方案
布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先校验,不符合则丢弃,从而避免了对底层存储系统的查询压力
缓存空对象
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源
但是这个方法会存在两个问题:
- 如果空值能够被缓存起来,这就意味着需要更多的空间来存储键,因为可能有很多空值的键
- 即使空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这就对于需要保持一致性的业务会有影响
缓存击穿(量太大,缓存过期)
概念
一个key非常热点,在不停地扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库
解决方案
设置热点数据永不过期
从缓存层面来看,没有设置过期时间,所以不会出现热点key过期后产生的问题
加互斥锁
分布式锁:使用分布式锁,保证对于每个key 同时只有一个线程去査询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。
缓存雪崩
概念
某一个时间段,缓存集中过期失效。如redis宕机
解决方案
redis高可用
既然Redis可能挂掉,就多设置几台Redis,挂掉一台之后还有其他的能用(异地多活)
限流降级
缓存失败后,通过加锁或者列队来控制读数据库写缓存的线程数量
数据预热
正式部署之前,先把可能的数据预选访问一遍,这样大部分数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀