缓存问题及解决方案

1、缓存穿透

缓存穿透是指查询一个一定不存在的数据,由于缓存中没有这个数据,所以会去查询数据库,但是数据库也没有这条数据,并且处于容错考虑,我们没有将这次查询的null写入缓存,这将导致每次请求这条数据都需要查询数据库,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。

解决:
将空结果(null)放进缓存,但它的过期时间会很短,最长不超过五分钟。

2、缓存雪崩

缓存雪崩是缓存中的数据在同一时间过期(即我们设置了相同的过期时间),导致缓存在某一时刻同时失效,恰好此时这条数据被超级多的请求访问,那么这些请求全部转发到DB,DB瞬时压力过重雪崩。

解决:
原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

3、缓存击穿

假设在我们的缓存中存放着一条非常"热点"的数据,它被多个线程超级频繁的访问。但是在那么一个时间点,它过期了,那么会发生什么了?大量的请求打进了数据库,瞬间造成数据库压力过大,极有可能数据库就这样宕掉了。这种单个热点的数据失效,我们把它称为缓存击穿;而如果是大面积的数据失效,我们则称它为缓存雪崩。

解决:
分布式锁(这是个什么玩意?)

4、分布式锁

上面记录到:一条热点数据在被多个线程高频访问的时候失效了,我们直观的解决方法就是再把它拿到缓存中不就行了嘛。可是,如果这样这样做的话,我们需要考虑一个问题:背景是多个线程并行访问,难不成让它们都去数据库取数据,然后放入缓存中?稍加思索就会明白,这样做肯定是不可取得,不说重复冗余,DB它也承受不住啊~ 那。。。。派个代表去数据库取数据,再放入缓存中?这么一想就靠谱多了,于是引出分布式锁的概念:保证有且只有这么一个线程代表可以去数据库取数据,并将其放入缓存中!

举个不太恰当的栗子:假设我们的系统有缓存服务器和数据库服务器,我们对数据库服务器上了锁,并且配有一把钥匙。有那么一个时间点,大量的线程发起请求去缓存服务器中访问同一个数据,结果发现它过期了(不存在了)。然后就需要那么 一个线程代表去数据库中取数据,放进缓存中供大家访问 ~ 于是乎,这个线程代表拿到了数据库的钥匙,可以打开数据库服务器的大门取数据,其他的线程们就只能在数据库外边转圈等它完成任务(这一过程称为自旋),最后大家都去访问缓存服务器了。这个小栗子大概就说明了分布式锁的用途和原理—— 控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。

悄咪咪留个坑——redisson,以后有机会再学习。。ok,就酱~

原文地址:https://www.cnblogs.com/simon-1024/p/11914313.html