到底啥是缓存雪崩,缓存击穿 缓存穿透

什么是缓存穿透
缓存穿透是指查询一个一定不存在的数据,由于缓存没有命中,这时候我们会数据库查询。出于容错考虑,当我们从数据库查询不到数据的时候,则不会写入缓存,这个可能导致每次请求都去数据库查询,失去了缓存的意义。在流量大的时候DB可能就会挂掉,如果有人利用这个不存在key频繁操作攻击我们的应用,这就是漏洞。
以查询用户信息为例,id=-1的用户是肯定不存在的,但是现在有10000个请求,其中9000个都是请求id=-1的这个用户,我们的数据库很容易的就被打死。

缓存穿透解决办法
简单粗暴,如果我们查询数据库结果为null的话,我们直接把这个null缓存起来,并且设置一个很短的过期时间。
以用户为例,我们把所有的用户id缓存到一个足够大的bitmap中,访问这个不存在的key的时候就行拦截,从而避免对数据库造成的压力
设置布隆过滤器(以后单开一篇博客介绍)
什么是缓存雪崩
数据未加载到缓存;缓存同一时刻大面积失效或者宕机,从而导致所有请求都去查询数据库,造成数据库CPU负载夜里过高,甚至宕机;都会造成缓存雪崩。
简单来说的话,就是因为缓存未命中或者缓存系统的宕机,从而引起数据库宕机成为缓存雪崩

如何解决缓存雪崩
如果针对缓存未加载或者缓存失效,那么尽量让缓存失效时间尽量分布均匀
如果针对缓存系统崩溃的话,可以构建redis主从模式+哨兵、redis cluster,避免全盘崩溃
hystrix熔断器做保护,避免MySQL被打死
缓存穿透和缓存雪崩的区别
好像缓存穿透和缓存雪崩有点相似,都是缓存没有查询到去查询数据库造成的宕机。但是这两点是有区别的,缓存穿透是查询一个一定不存在的数据,而缓存雪崩其中一点是查询的数据是存在于数据库中的,一定不要搞混了。

缓存击穿
针对某一个key,我们设置了过期时间的key而失效,或者还未加载,如果某一时间被超高频率的访问,也有可能会造成数据库挂掉。与缓存雪崩相比,雪崩针对的是以系列key,而击穿是针对一个key。
比如10点的时候要去抢购一个手机,10点这一刻有N多请求访问服务器,并且这时候我们的数据还没有加入到缓存中,导致所有请求都去数据库查询,这样数据库就很容易挂掉。

如何解决缓存击穿
让key一直存在
使用互斥锁
if (key不存在){
        if(tryLock()) {
                数据库查询
                释放锁
                返回数据
        } else {
                while(!tryLock()) {
                    Thread.sleep(100);    //暂停一会,防止cpu空转
                }
                查询缓存,写入数据
        }
}

发布了112 篇原创文章 · 获赞 266 · 访问量 26万+

猜你喜欢

转载自blog.csdn.net/fujiakai/article/details/89101062