Redis缓存一致性、缓存穿透、缓存击穿

本文探讨了在使用Redis时如何实现数据一致性,包括内存淘汰策略、TTL的应用,以及主动更新的不同方案。还针对缓存穿透和缓存击穿问题提出了空缓存、布隆过滤和锁定机制等解决方案。
摘要由CSDN通过智能技术生成

前言

Redis作为缓存中间件,在项目开发中常常用于解决高并发,以及数据缓存来实现应用的性能的提升,但是正因为此,Redis带来了一些不容忽视的问题


一、如何实现redis的数据一致性?

1.1内存淘汰

redis通过分析内存占用情况后,会根据不同的策略进行缓存清理;

Redis多种内存淘汰策略
noeviction新写入操作会报错。这是默认的淘汰策略
allkeys-lru在键空间中,移除最近最少使用的key
allkeys-lfu在键空间中,移除最不经常使用的key
volatile-lru在设置了过期时间的键空间中,移除最近最少使用的key
volatile-random在设置了过期时间的键空间中,随机移除某个key
volatile-ttl在设置了过期时间的键空间中,优先移除剩余生存时间(TTL)较短的key
allkeys-random在键空间中,随机移除某个key

通过配置文件设置(修改redis.conf文件):

maxmemory-policy allkeys-lru

通过命令行:

127.0.0.1:6379> CONFIG SET maxmemory-policy allkeys-lru

1.2TTL(超时剔除)

一般我们在使用redis的时候,都应该设置缓存的超时时间,这样一定程度上能够保证一致性(最终的一致性),这个还是比较简单的,基本上不用怎么维护,一般就是根据业务的特性制定比较合适的TTL

1.3主动更新

主动更新,我们自己去编写代码来实现,一般会涉及到三种方案;

1.3.1第一种方案:

Cache Aside Pattern: 由缓存的调用者,在更新数据库的同时去更新缓存

1.3.1.1删除缓存还是修改缓存?

更新缓存:每次更新数据库都需要更新缓存,无效写操作较多

删除缓存:更新数据是让缓存失效,查询时在更新缓存

1.3.1.2数据变更时是先操作数据库还是先操作缓存?

先删缓存

会出现一种情况,两个线程,线程一删除缓存后另一个线程趁虚而入,线程一还没来得及更新数据库,这个时候另一线程去数据库查询得到的数据还是旧数据缓存到redis中,这个时候就会造成数据不一致,这种概率还是挺高的,因为修改数据库要比查询数据库慢

先操作数据库

也会出现一种情况 由于某种原因缓存失效,这个时候一个线程来访问,没有得到数据,要去数据库查找数据将要写入缓存的时候,恰有一个线程来更新数据库并删除缓存,而这个时候第一个线程查到的旧数据缓存到redis中造成数据不一致,这样的概率极低

1.3.2第二种方案:

Read/Write Through Pattern: 缓存与数据库整合为一个服务,有服务来维护一致性,调用者调用该服务,无需关心缓存一致性问题

1.3.3第三种方案:

Write Behind Caching Patter: 调用者只操作缓存,有其他线程异步的将缓存数据库,保证最终一致性

二、缓存穿透

2.1问题描述

缓存穿透就是:用户在访问数据时,缓存中没有数据,并且数据库也不存在该数据,这样会造成每次请求都会打到数据,给数据库造成巨大压力,可能造成雪崩。

2.2问题解决

2.2.1方案一:

空缓存:

就是在我们查询数据库时,如果需要缓存数据不存在,那么我们就进行数据的空缓存,给这个key的value设置成空字符串;

2.2.2方案二:

布隆过滤:

布隆过滤基于概率来实现,就是将传输进来的的key进行k次hash运算,找到对应key所对应的二进制向量位是否时1来判断当前key对应的数据存不存在

2.2.3方案三:

主要作为预防的存在,就是设计我们的key具有一定规律性,避免一些不怀好意的程序员进行破坏,进行key的预判断,提前拦截;这个我感觉和布隆过滤器一个原理

三、缓存击穿

3.1问题描述

缓存击穿是指当缓存系统中没有某个热点数据时,而这时大量的请求又同时对这个数据进行访问,请求会穿过缓存直接打到数据库上,导致数据库短时间内承受大量请求压力。这在高并发系统中是一个需要重点防范的问题,因为它可能会导致数据库性能急剧下降甚至崩溃。

3.2解决缓存击穿问题主要有以下几种方案:

  1. 主动设置空缓存:当接受对于数据库中都没有的查询请求时,主动在缓存中写入空数据。为了避免请求过多导致空数据过多负载加重,可以给每一个空数据都设置一个过期时效。这样,对于同一个空数据的请求,只有第一次会访问数据库,其余的时候都是停止在缓存层面,有效的缓解了数据库的压力。
  2. 使用互斥锁:在缓存失效的时候,使用互斥锁来保护对数据库的访问,只有一个请求能够重新加载缓存数据,其他请求等待或返回旧数据。这可以避免在缓存失效的瞬间,大量请求同时涌入数据库导致的问题。
  3. 将热点数据设置为永不过期:确保即使缓存失效,数据仍然存在于缓存中,从而减轻数据库负担。

总结

Redis使用中也经常会有很多的问题,但也有不同的对策,基于以上的解决方案,也是经常使用到的方案,仅供参考

  • 47
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值