发布时间:2024-04-17 18:01
现在面试一聊到Redis基本上都会问到穿透、击穿、雪崩,然而我觉得实际上大多数企业是碰不上这类问题的,不过现在面试都要求你虽然没吃过猪肉必须要见过猪跑的☝ᖗ乛◡乛ᖘ☝,所以我们还是要了解了解的,不要被几个高大上的名词所唬住,实际上问题本身现象并不复杂,一起看来来怎么解决吧!
缓存穿透主要强调的就是专门用缓存中肯定不存在的key来查询,导致每次查询都会落到数据库上,从而造成数据库压力过大,最终服务不可用。
我形象的把这种方式理解为以毒攻毒,你利用我key不存在的漏洞,我就让key必定存在,这样大多数的查询就又可以通过缓存拦截下来了,value值已经不重要了。
1、这种方式很有可能会造成内存中缓存了大量无效的key,所以必须要有一个过期时间,避免造成过多的内存消耗,频繁的触发内存淘汰机制。
2、每一次的请求时,还是会造成很多请求落到数据库中,大量的并发请求打过来,可能还没来及写入缓存。
布隆过滤器通常是通过多次hash算法,让你的key映射到二进制向量中,所以数据是按位存储,只需要少量的内存空间即可存储大量的数据,一般做法就是当带着key请求时,先从布隆过滤器中查询,如果布隆中存在则认为Redis缓存中也存在,如果布隆中不存在,则Redis缓存中肯定不存在,当然由于存在Hash冲突的可能,所以即使布隆中认为存在,实际上缓存里也不一定真的存在。
1、误判性,布隆过滤器并不能做到100%过滤掉所有无效key的请求,要求的准确性越高,每次计算的代价也就越高,一般可以再使用一个map或者链表用来存储可能会被误判的key。
2、增加了复杂性,要能使用布隆过滤器的前提是元素必须要先添加到过滤器中,这就要求每次缓存的元素除了要添加到Redis中还必须要添加到布隆过滤器中。
3、数据一旦被添加到布隆过滤器中以后,再想删除就非常的困难。
有时候可以根据定义key时内部约定的规则,直接过滤掉一部分不符合规则的key。
缓存击穿一般情况下指的是,某个或者某些key,当请求量特别大的时候,突然失效了,导致大量的请求直接打到数据库中。
对于热点key需要能够做到实时的发现,然后避免热点key的失效,比如在失效前提前更新。
实际上对于热点数据除了缓存在Redis中之外还可以在本地也缓存一份,不过本地缓存就要考虑Redis与本地缓存一致性问题以及本地服务在集群部署时多个节点数据一致性的问题。
利用锁来控制,当缓存中数据不存在时,让同一时间只能有一个线程进行更新缓存的操作,其他线程要么自旋等待缓存更新成功,要么直接返回。
雪崩现象强调的不是单个缓存的问题,而是服务器中大批的缓存在同一时间失效,导致多个入口的请求访问到数据库。
在设置缓存失效时间时,给失效时间加上随机值,避免造成大量的key在同一时间失效,不过这种解决方式并不能解决业务上强制规定的失效时间,比如业务中就要求12点失效,差一分一秒都不可以,那么就不能使用这种方式了。
其实多个key失效的场景,也可以当做单个key来处理,也就是按照缓存击穿的处理方式也可以解决缓存雪崩的问题。
为了顾全大局,有时候像限流、熔断等这样的措施还是非常有必要准备的,比如redis服务挂了,那就是最大的缓存雪崩现象,所以为了避免整个服务不可用,只能牺牲部分可用性。