1.缓存穿透
介绍:缓存穿透是指查询一个一定不存在的数据,这将导致这个不存在的数据每次请求都要到数据库去查询,可能导致数据库挂掉。
解决方案:
1.1布隆过滤器:
使用布隆过滤器来过滤掉那些明显无效的请求,从而减轻数据库压力,但是布隆过滤器是有缺点,存在一定的误判率,可以设置,最好5%以下。
布隆过滤器介绍:
布隆过滤器主要是用于检索一个元素是否在一个集合中。使用的是redisson实现的布隆过滤器。它的底层主要是先去初始化一个比较大数组,里面存放的二进制0或1。在一开始都是0,当一个key来了之后经过几次hash计算,模于数组长度找到数据的下标然后把数组中原来的0改为1,这样的话,三个数组的位置就能标明一个key的存在。查找的过程也是一样的。
为什么会出现误判率呢,因为key经过hash函数计算可能会出现哈希冲突,导致不同的key经过几次hash函数计算后得到的下标一样,这会导致在数据库不存在的key也能在布隆过滤器找到,同理,在删除布隆过滤器的时候,可能会删除同一个下标的key(误删),两个不同的key地址一样。
1.2.空值缓存:
对于查询结果为空的请求,可以将空值也缓存起来,即将键设置为对应的空值(如NULL),并设置适当的过期时间(防止存储太多的null值),这样下次请求相同的无效数据时可以直接从缓存返回NULL,而不是去查询数据库。
2缓存击穿
介绍:问题描述:缓存击穿是指某个热点数据kry过期或被删除,恰好大量请求同时访问这个热点数据,没有缓存就直接去访问数据库,使得数据库负载骤增。可能导致数据库挂掉。
解决方案:
2.1分布式锁
Redisson分布式锁,当大量请求到接口时,先判断有没有缓存了,没有的话,去获取分布式锁,只有一个请求能拿到锁,并可以去请求数据并把数据缓存到redis。其它请求就可以直接拿缓存返回了,不用去数据库拿数据了。
2.2 缓存设置为逻辑(永不)过期
1.在设置key的时候,设置一个过期时间字段一块存入缓存中,不给当前key设置过期时间
2.当查询的时候,从redis取出数据后判断时间是否过期
3.如果过期则开通另外一个线程进行数据同步,当前线程正常返回旧数据(返回之前的,不是最新数据)。
两种方法比较:
1.如果选择数据的强一致性,建议使用分布式锁的方案,性能上可能没那么高,也有可能产生死锁的问题
2.如果选择key的逻辑删除,则优先考虑的高可用性,性能比较高,但是数据同步这块做不到强一致。
3.缓存雪崩
缓存雪崩是指大量缓存数据在同一时间失效,导致大量请到数据库上请求数据,可能使数据库挂掉。
解决方案:
3.1 缓存设置随机的过期时间
在缓存数据的过期时间上增加一个随机的值,以分散缓存失效时间,避免大规模同时失效。