Redis 17 缓存穿透 缓存击穿 缓存雪崩


参考源

https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0

版本

本文章基于 Redis 6.2.6

使用缓存的问题

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

但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。

如果对数据的一致性要求很高,那么就不能使用缓存。

另外的一些典型问题就是,缓存穿透缓存雪崩缓存击穿。目前,业界也都有比较流行的解决方案。

缓存穿透

概念

这里先介绍下日常使用缓存的逻辑:

查询一个数据,先到缓存中查询。

如果缓存中存在,则返回。

如果缓存中不存在,则到数据库查询。

如果数据库中存在,则返回数据,且存到缓存。

如果数据库中不存在,则返回空值。

缓存穿透

缓存穿透出现的情况就是数据库和缓存中都没有。

这样缓存就不能拦截,数据库中查不到值也就不能存到缓存。

这样每次这样查询都会到数据库,相当于直达了,即穿透

这样会给数据库造成很大的压力。

解决方案

布隆过滤器

布隆过滤器是一种数据结构,对所有可能查询的参数以 hash 形式存储,在控制层先进行校验,不符合则丢弃,从而避免了对底层存储系统的查询压力。

Redis 17 缓存穿透 缓存击穿 缓存雪崩

缓存空对象

当存储层不命中后,即使返回的空对象也将其缓存起来,同时会设置一个过期时间,之后再访问这个数据将会从缓存中获取,保护了后端数据源。

Redis 17 缓存穿透 缓存击穿 缓存雪崩

但是这种方法会存在两个问题:

  • 如果空值能够被缓存起来,这就意味着缓存需要更多的空间存储更多的键,因为这当中可能会有很多的空值的键。

  • 即使对空值设置了过期时间,还是会存在缓存层和存储层的数据会有一段时间窗口的不一致,这对于需要保持一致性的业务会有影响。

缓存击穿

概念

缓存击穿,是指一个 key 非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问。

当这个 key 在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。

当某个 key 在过期的瞬间,有大量的请求并发访问,这类数据一般是热点数据。

由于缓存过期,会同时访问数据库来查询最新数据,并且回写缓存,会导使数据库瞬间压力过大。

解决方案

设置热点数据永不过期

从缓存层面来看,没有设置过期时间,所以不会出现热点 key 过期后产生的问题。

加互斥锁

分布式锁:使用分布式锁,保证对于每个 key 同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只能等待。

这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大。

缓存雪崩

概念

缓存雪崩,是指在某一个时间段,缓存集中过期失效。

产生雪崩的原因之一,比如马上就要到双十一零点,很快就会迎来一波抢购。

这波商品时间比较集中的放入了缓存,假设缓存一个小时。

那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。

而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。

于是所有的请求都会达到存储层,存储层的调用量会暴增,造成存储层也会挂掉的情况。

Redis 17 缓存穿透 缓存击穿 缓存雪崩

其实集中过期,倒不是非常致命。

比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。

因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存。

这个时候,数据库也是可以顶住压力的,无非就是对数据库产生周期性的压力而已。

而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。

解决方案

搭建集群

实现 Redis 的高可用,既然一台服务有可能挂掉,那就多增设几台服务。

这样一台挂掉之后其他的还可以继续工作,其实就是搭建的集群。

限流降级

在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。

比如对某个 key 只允许一个线程查询数据和写缓存,其他线程等待。

数据预热

数据加热的含义就是在正式部署之前,先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。

在即将发生大并发访问前手动触发加载缓存不同的 key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

原创文章,作者:carmelaweatherly,如若转载,请注明出处:https://blog.ytso.com/267046.html

(0)
上一篇 2022年6月14日
下一篇 2022年6月14日

相关推荐

发表回复

登录后才能评论