美文网首页
缓存穿透、缓存击穿、缓存雪崩区别和解决方案

缓存穿透、缓存击穿、缓存雪崩区别和解决方案

作者: 小飞剑客 | 来源:发表于2020-04-29 14:16 被阅读0次

    欢迎来到飞之折翼的简书,待双翼饱满就是飞翔之际!

    前言

    Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。

    但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。如果对数据的一致性要求很高,那么就不能使用缓存。

    另外的一些典型问题就是,缓存穿透、缓存雪崩和缓存击穿,这是设计一个缓存系统,不得不要考虑的问题!

    缓存处理流程

    正常的一个缓存处理流程都会这样设计:请求数据 ,后段先从缓存中get数据,get到直接返回结果,get不到时从DB中取,DB取到更新缓存,并返回结果,DB也没取到,那直接返回空结果,流程见下图:

    但这样很容易引起缓存穿透、缓存击穿、缓存雪崩!!!!!

    缓存穿透

    缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。

    解决方案

    有很多种方法可以有效地解决缓存穿透问题:

    最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力;

    接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;

    另外也有一个更为简单粗暴的方法,如果一个查询返回的数据为空,仍然把这个空结果进行缓存,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。

    缓存雪崩

    缓存雪崩是指在我们设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,请求全部转发到DB,DB瞬时压力过重雪崩。

    解决方案

    缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。

    如果缓存数据库是分布式部署,将热点数据均匀分布在不同搞得缓存数据库中。

    设置热点数据永远不过期。

    缓存击穿

    对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。

    解决方案

    1.使用互斥锁(mutex key)

    这种解决方案思路比较简单,就是只让一个线程构建缓存,其他线程等待构建缓存的线程执行完,重新从缓存获取数据就可以,如下图:

    2."提前"使用互斥锁(mutex key)

    在value内部设置1个超时值(timeout1), timeout1比实际的memcache timeout(timeout2)小。当从cache读取到timeout1发现它已经过期时候,马上延长timeout1并重新设置到cache。然后再从数据库加载数据并设置到cache中。

    3."永远不过期"

    这里的“永远不过期”包含两层意思:

    a.从redis上看,确实没有设置过期时间,这就保证了,不会出现热点key过期问题,也就是“物理”不过期。

    b. 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期

    方案对比

    总结

    没有最好,只有更好!

    只有熟悉自己的业务系统,才能找到最合适自己系统的解决方案。

    相关文章

      网友评论

          本文标题:缓存穿透、缓存击穿、缓存雪崩区别和解决方案

          本文链接:https://www.haomeiwen.com/subject/qvvnwhtx.html