首页 > 编程知识 正文

怎么防止redis雪崩,redis缓存并发更新

时间:2023-05-06 02:12:36 阅读:29680 作者:2159

目录

一.缓存直通

解决方案:

二.现金雪崩

解决方案:

三.缓存销毁

解决方案:

在生产环境中,出于许多原因,访问请求必须绕过缓存并访问数据库的长期保留层。 它不会影响Redsi缓存服务器,但会增加数据库负载,降低缓存的作用

另一方面,缓存透明度缓存透明度是查询不存在的数据,既不命中缓存层,也不命中持久层。 在日常工作中,从容错的角度来看,如果从持久层找不到数据,就不会写入缓存层;由于缓存透明度,每次请求不存在的数据时都会查询持久层,从而失去缓存保护后端的永久含义

缓存穿透示意图:

缓存直通问题可能会增加后端存储负载,而且许多后端持久层不具有高并发性,因此后端存储也可能出现故障。 通常,可以通过编程方式对总调用数、缓存层命中数进行计数。 如果同一Key的缓存命中率较低,则可能出现缓存直通问题。

缓存直通的基本原因有两个。 第一,自身的业务代码和数据存在问题(例如,set和get的密钥不一致);第二,通过恶意攻击和爬虫等获取大量的空命中)在线商城的商品数据,在超大循环中增加商品的ID )。

http://www.Sina.com/http://www.Sina.com /

缓存空对象:持久层没有命中时,对key进行set(key,null )

缓存空对象会导致两个问题。 第一,value为null并不意味着不占用内存空间。 缓存空值意味着缓存层中存储了更多的密钥,需要更多的内存空间。 有效的方法是为这类数据设置较短的过期时间并使其自动删除。 第二,缓存层和存储层数据之间存在一定的时间段不一致,可能会影响业务。 例如,如果将过期时间设置为5分钟,则此时将数据添加到存储层时,缓存层和存储层中的数据会不匹配。 在这种情况下,可以使用消息系统等清除缓存层次结构中的空对象

解决方案:

在访问缓存层和存储层之前,用bloom过滤器预先保存存在的key,进行第一层拦截,在收到对key的请求时首先用bloom过滤器验证key是否存在,如果存在,进入缓存层、存储层可以使用bitmap创建光晕滤波器。 该方法适用于数据命中率不高、数据相对固定、实时性较差的APP应用场景,代码维护复杂,但缓存空间占用较少。

布隆过滤器实际上是一个长二进制向量和一系列随机映射函数。 布隆过滤器可用于获取元素是否在集合中。 其优点是空间效率和查询时间远远超过一般算法,难以达到一定的误识别率和删除。

1. 缓存空对象

初始情况下,bloom过滤器是长度为m的位数组,每个位都设置为0。

当添加元素x时,x使用k个散列函数获得k个散列值,并从m中提取馀数,且相应的位设定为1。

判断y是否属于该集合,对y使用k个散列函数得到k个散列值,对m取馀数,如果所有对应的位置都为1,则认为y属于该集合(散列冲突,可能存在误判定),并可以通过增加散列函数和增加二进制位数组的长度来降低误报率。

2.布隆过滤器拦截

一个key映射数组中有多个位,一个位用于多个key。 也就是说,是多对多的关系。 如果一个key图的所有比特值都是1,则判断为存在。 然而,如果key1和key2被同时映射到下标为100的位,并且key1不存在并且key2存在,则可能发生错误率

算法描述:

二、缓存平衡器有效保护存储层,因为缓存层承载大量请求,但如果缓存层由于某些原因不可用(停机),或者超时时间相同

时间段失效(大批key失效/热点数据失效),大量请求直接到达存储层,存储层压力过大导致系统雪崩。

解决方案: 可以把缓存层设计成高可用的,即使个别节点、个别机器、甚至是机房宕掉,依然可以提供服务。利用sentinel或cluster实现。采用多级缓存,本地进程作为一级缓存,redis作为二级缓存,不同级别的缓存设置的超时时间不同,即使某级缓存过期了,也有其他级别缓存兜底缓存的过期时间用随机值,尽量让不同的key的过期时间不同(例如:定时任务新建大批量key,设置的过期时间相同)三、缓存击穿

系统中存在以下两个问题时需要引起注意:

当前key是一个热点key(例如一个秒杀活动),并发量非常大。重建缓存不能在短时间完成,可能是一个复杂计算,例如复杂的SQL、多次IO、多个依赖等。

在缓存失效的瞬间,有大量线程来重建缓存,造成后端负载加大,甚至可能会让应用崩溃。

解决方案:

1. 分布式互斥锁

      只允许一个线程重建缓存,其他线程等待重建缓存的线程执行完,重新从缓存获取数据即可。set(key,value,timeout)

 

2. 永不过期

从缓存层面来看,确实没有设置过期时间,所以不会出现热点key过期后产生的问题,也就是“物理”不过期。从功能层面来看,为每个value设置一个逻辑过期时间,当发现超过逻辑过期时间后,会使用单独的线程去更新缓

2种方案对比:

分布式互斥锁:这种方案思路比较简单,但是存在一定的隐患,如果在查询数据库 + 和 重建缓存(key失效后进行了大量的计算)时间过长,也可能会存在死锁和线程池阻塞的风险,高并发情景下吞吐量会大大降低!但是这种方法能够较好地降低后端存储负载,并在一致性上做得比较好。

“永远不过期”:这种方案由于没有设置真正的过期时间,实际上已经不存在热点key产生的一系列危害,但是会存在数据不一致的情况,同时代码复杂度会增大。

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。