到底什么是缓存穿透,缓存雪崩,缓存击穿

什么是缓存穿透


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

缓存穿透解决办法

  1. 简单粗暴,如果我们查询数据库结果为null的话,我们直接把这个null缓存起来,并且设置一个很短的过期时间。
  2. 以用户为例,我们把所有的用户id缓存到一个足够大的bitmap中,访问这个不存在的key的时候就行拦截,从而避免对数据库造成的压力
  3. 设置布隆过滤器(以后单开一篇博客介绍)

什么是缓存雪崩


数据未加载到缓存;缓存同一时刻大面积失效或者宕机,从而导致所有请求都去查询数据库,造成数据库CPU负载夜里过高,甚至宕机;都会造成缓存雪崩。
简单来说的话,就是因为缓存未命中或者缓存系统的宕机,从而引起数据库宕机成为缓存雪崩

如何解决缓存雪崩

  1. 如果针对缓存未加载或者缓存失效,那么尽量让缓存失效时间尽量分布均匀
  2. 如果针对缓存系统崩溃的话,可以构建redis主从模式+哨兵、redis cluster,避免全盘崩溃
  3. hystrix熔断器做保护,避免MySQL被打死

缓存穿透和缓存雪崩的区别

好像缓存穿透和缓存雪崩有点相似,都是缓存没有查询到去查询数据库造成的宕机。但是这两点是有区别的,缓存穿透是查询一个一定不存在的数据,而缓存雪崩其中一点是查询的数据是存在于数据库中的,一定不要搞混了。

缓存击穿


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

如何解决缓存击穿

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

猜你喜欢

转载自blog.csdn.net/qq_25448409/article/details/86566859