缓存穿透
缓存穿透是指用户想要查询一个数据, 发现redis内存中没有, 也就是没有缓存命中,于是向持久层数据库查询,发现也没有, 于是本次查询失败, 当用户很多的时候, 缓存中都没有, 于是都去请求持久层数据库, 这会给持久层数据库造成很大压力, 这就是缓存穿透
解决方案
1.布隆过滤器
布隆过滤器是一种数据结构,对所有可能查询的参数 一hash的形式存储。在控制层先进行校验,不符合的则丢弃,从而避免了对底层存储系统的查询压力
2.缓存空对象
当持久化层不命中后,将返回的空对象存储起来,同时设置一个过期时间,之后再访问这个数据就从缓存中获取,保护持久层数据源
对空值设置了过期时间,还会存在缓存层和存储层的数据有一段时间窗口不一致,对于需要保持一致性的业务会有影响
缓存击穿
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期), 这时由于并发用户特别多, 同时读缓存没读到数据, 又同时去数据库去取数据, 引起数据库压力瞬间增大, 造成过大压力.例如当微博热搜, 这个时候这个点的访问量巨大, 然后在某个时刻该热点的缓存过期或者其他情况导致缓存中暂时没有该热点, 这个时候依然大量并发就会全部集中到数据库去查询最新数据并回写缓存, 很有可能在这一瞬间就导致数据库崩溃
解决方案
1.设置热点数据永不过期
从缓存层面来看, 没有设置过期时间, 所以不会出现热点key过期后产生的问题.但是有可能会逐渐的让redis缓存增加, 内存占用庞大
2.加互斥锁
分布式锁: 使用分布式锁, 保证每个key同事只有一个线程去查询后端服务, 其他县城没有获得分布式锁的权限, 因此只需要等待即可. 这种方式将高并发的压力转移到了分布式锁, 因此对分布式锁的考验很大
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间, 而查询数据量巨大, 引起数据库压力过大甚至down机. 和缓存击穿不同的是, 缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了, 很多数据都查不到从而查数据库.
解决方案
1.增加集群中服务器的数量
2.缓存失效后, 通过加锁或者队列来控制读数据库写缓存的线程数量, 对某个key只允许一个线程查询数据和写缓存, 其他线程等待
3.正式部署之前, 把可能的数据提前访问一遍, 可能大量访问的数据就会加载到缓存中, 加载不同的key, 设置不同的过期时间, 让缓存时间尽量均匀