一、穿透
1、什么是穿透
用户想要查询一个数据,发现redis内存数据库没有,也就是缓存没有命中,于是向持久层数据库查询。发现也没有,于是本次查询失败。当用户很多的时候,缓存都没有命中,于是都去请求了持久层数据库。这会给持久层数据库造成很大的压力,这时候就相当于出现了缓存穿透。
2、解决方案
方案1:布隆过滤器
是一种数据结构,对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力
方案2:缓存空对象
当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源;
但是这种方法会存在两个问题:
1、如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键;
2、即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。
方案3:设置可访问的名单
使用bitmap类型定义一个可以访问的名单,名单id作为bitmaps偏移量,每次访问和bitmap里面的id进行比较,如果访问id不在bitmaps里面进行拦截
方案4:实时监控
发现redis命中率开始急速降低 配查访问对象和数据 设置黑名单限制
二、击穿
1、什么是击穿
是指一个key非常热点,在不停的扛着大并发,大并发集中 对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一 个屏障上凿开了一个洞。 当某个key在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据,由于缓存过期,会同时访 问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。
2、解决方案
1、预先设置热门数据:redis高峰访问之前,把一些热门数据提前存入到redis里面,加大这些热门数据的key时间长
2、实时调整:现场监控哪些数据热门,实时调整key过期时长
3、使用锁:
缓存失效的时候(判断拿出来值为空),不立即去load db;
先使用缓存工具的某些带成功操作返回值的操作比如redis的SETNX
三、缓存雪崩问题
1、什么是缓存雪崩
缓存雪崩:数据同一时间大量key的集中过期过期,请求全部转发 到DB,DB瞬时压力过重雪崩。服务器崩掉问题
2、解决方案
1、构建多级缓存架构:nginx缓存+redis缓存+其他缓存
2、使用锁或队列:用加锁或者队列的方式保证不会有大量线程对数据库一次性进行读写,避免失效时大量的并发请求落到底层存储系统,不适用高并发情况
3、设置过期标志更新缓存:记录缓存数据是否过期(设置提前量),如果过期会触发通知另外的线程在后台去更新实际key的缓存
4、将缓存失效时间分散开:比如可以在原有的失效时间加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间重复率就会降低,就很难引发集体失效的事件