最近翻看之前的一个收藏的时候,看到了缓存穿透这个词,不是很了解,于是百度了一下,下面说下自己对这个问题的见解.。
很多博客我是不忍心看,就是这儿抄点,那儿抄点,可能写的人自己也不知道怎么回事,所以就很晦涩难懂了。
以这篇博文为例,这篇是我看到的相对而言比较好的,原文也是转载的,说说我个人的看法:
https://blog.csdn.net/doujinlong1/article/details/82024340
缓存失效的几种形式
1.缓存穿透
本质原因:因为我们做缓存,一般不把空数据置入缓存中,不管是系统故障还是查不到数据,所以当有这种数据时,缓存形同虚设,每次查询都会和数据库进行交互。
要不要做:一般的系统是没有必要做这些的,因为可能并发量或者数据量都不是很大。
第一点,缓存查到空数据,本身这样的sql耗时不会太长,这是sql本身的优化。而且一般企业可能都会有sql查询分析,便于我们优化慢查询,查询频率高的考虑做缓存,如果已经做了缓存,那么就可能是缓存穿透发生了。
第二点,针对缓存穿透发生,我们可以做监控,做日志分析。如果要做的话,建议全局做。
第三点,针对恶意攻击,我觉得如果确定是缓存穿透这种恶意攻击,可以上升到全局恶意攻击的高度,做ip拦截,封禁账号等。
怎样做:
1.缓存空数据,这个应该是比较直接的解决方案。但是我建议外部预留清空缓存的接口,在数据不为空的时候,可以立马清空缓存,读取DB的数据到缓存。当然这个有没有必要呢,如果你缓存空数据的时间短,也不是非常有必要。
2.布隆过滤器。我看过几篇文章,也不知道他们到底要怎么做,说得很含糊。布隆过滤器我也用过,是做大数据去重,和校验某个数据在大数据量中是否存在,比如url黑名单这种应用,升级版的还有布谷鸟过滤器。它的实现原理是通过多次hash多个位,将这些位 置为1,当你需要验证某个数据是否存在的时候,也是同样的hash算法,如果这些位都是1,表示数据存在。它的最大好处是节省内存,从而可以加载大数据量。如果我用布隆过滤器做这个,可能就是定时任务调用业务sql,有数据的key直接hash到位图上,这样便可以判断相应的key有没有对应数据了,当然不仅仅这么实现,如果想要健壮还有很多优化点。
2.缓存雪崩
这个没啥说的,参见原文。通过随机缓存时间来控制尽量少的缓存在同一时间内失效。当然这个随机缓存时间是次要缓存时间,可以随机个1s到240s等等,主要缓存时间还是根据业务来 ,比如不常更新,而同时又会被经常查询的数据肯定比常更新常查询的数据缓存时间长。缓存时间=主要缓存时间+次要缓存时间。
3.缓存击穿
本质原因:缓存恰好失效时,又有高并发请求。换句话说,在 缓存过期后 到 再次从数据库中查询数据置入缓存 这一段时间内,发生了高并发请求。比如这期间发生了10000个请求,第一个请求发现缓存中没有数据,从数据库中查询,这之后的1微秒中,又有9999个请求过来了,也发现缓存中没有数据,因为第一个请求可能还没开始执行查询,或者查询了,还没来得及置入缓存中,所以这9999个请求全部去和数据库交互,对数据库造成了非常大的压力。
解决方案:分布式锁确实是一种解决方案,但是用Redis做分布式锁不是最好的解决方案,因为Redis遵循的是AP理论,而CP更适合做分布式锁,比如zookeeper。但是这里,你用Redis就算发生问题了,问题也不是很大,因为就算数据不一致,多个请求拿到了锁,也不过是多请求了几次,问题不是很大。所以就看你们公司用什么做分布式锁,拿来即用就行。现在分布式锁应用也是非常广泛了,所以我建议用一套比较健壮的锁解决方案,在涉及到非常重要的数据的时候,比如钱,就真的必须0容错了!