Redis(七)Redis缓存数据一致性及缓存问题(缓存穿透、缓存击穿、缓存雪崩)

目录

缓存存在的意义

如何保证缓存和数据库数据一致性

缓存问题

1、缓存穿透-大量请求在数据库查不到相应数据

2、缓存击穿-请求量太大,缓存突然过期

3、缓存雪崩-在某一个时间段,缓存集中过期失效或者Redis宕机


缓存存在的意义

将一些数据(最近访问的)放在缓存中,当客户端需要访问数据库中数据时,可以先访问缓存,如果它里面存在这样对应的数据就不会去访问数据库,从而减小数据库的压力。

那么客户端对数据库的操作有 增删改查,但是只有当查数据库里面的信息时才会先访问缓存,那么缓存里的数据时如何更新的?它会不会有数据更新不及时的问题?

如何保证缓存和数据库数据一致性

缓存数据插入的时机:

当客户端来说,查询数据时的步骤如下:

1、首先到缓存查询数据,如果数据存在则直接获取数据返回

2、如果缓存不存在,需要查询数据库,从数据库获取数据并插入缓存,将数据返回

3、当第二次查询这个数据时并且这个数据在缓存中尚未过期,查询操作就可以查询缓存拿到对应的数据

缓存更新数据(3种方案):

客户端对数据库进行一个更改操作:

1、先删除缓存在更新数据库

进行更新数据库数据时,先删除缓存,然后更新数据库,后续的请求再次读取数据时,会从数据库中读取数据更新到缓存

存在问题:删除缓存之后,更新数据库之前,这个时间段内如果有新的请求过来,就会从数据库中读到旧的数据并写入缓存,再次造成数据不一致,并且后续读操作都是旧数据

2、先更新数据库在删除缓存

进行更新操作,先更新数据库,成功之后,在删除缓存,后续请求将新数据写回缓存

存在问题:更新MySQL之后和删除缓存之前的这段时间内,请求读取的还是缓存内的旧数据,不过等数据库更新完成后,就会恢复一致

3、异步更新缓存

数据库的更新操作完成后不直接操作缓存,将操作命令封装成消息放到消息队列里,然后由Redis自己去更新数据,消息队列保证数据操作数据的一致性,保证缓存数据的数据正常

缓存问题

1、缓存穿透-大量请求在数据库查不到相应数据

概念:

缓存穿透是指用户想查询一个数据,发现Redis中没有,也就是缓存没有命中,就像持久性数据库发起查询,发现数据库也没有这个数据,于是查询失败了,当用户请求很多的情况下,缓存没有命中,数据库也没有数据,会都直接访问数据库,给数据库造成很大的压力,这就是缓存穿透

解决方案:

第一种解决方案:使用布隆过滤器

(判断对应的数据是否在这个数据库里,使用布隆过滤器,如果全返回1,则可能存在;如果返回结果存在一个不是1,那就肯定不在这个数据库中,这样就可以拒绝这个请求去访问数据库,大大降低数据库的压力)

布隆过滤器(Bloom Filter)的核心实现是一个超大的位数组和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k。

以上图为例,具体的操作流程:假设集合里面有3个元素{x, y, z},哈希函数的个数为3。首先将位数组进行初始化,将里面每个位都设置位0。对于集合里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数组上面的一个点,然后将位数组对应的位置标记为1。查询W元素是否存在集合中的时候,同样的方法将W通过哈希映射到位数组上的3个点。如果3个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。反之,如果3个点都为1,则该元素可能存在集合中。注意:此处不能判断该元素是否一定存在集合中,可能存在一定的误判率。可以从图中可以看到:假设某个元素通过映射对应下标为4,5,6这3个点。虽然这3个点都为1,但是很明显这3个点是不同元素经过哈希得到的位置,因此这种情况说明元素虽然不在集合中,也可能对应的都是1,这是误判率存在的原因。

使用布隆过滤器之后,将存储的数据放入布隆过滤器,每次数据查询首先查询布隆过滤器,当在过滤器中判断存在时在到数据库缓存查询,如果没有进入数据查询,如果在过滤器不存在,则直接返回告诉用户该数据查不到,这样能大大减轻数据库查询压力

第二种方案:缓存空对象

当数据库数据不存在时,及时返回的空对象也缓存起来,同时设置一个过期时间,之后在访问数据将从缓存中获取,保护了数据库

存在问题:

1、对空值设置过期时间,会存在更新数据库数据到缓存数据失效的一段时间,缓存数据有问题,会对要保证数据一致性的业务造成影响

2、会需要更多的空间来存储更多的控制,造成内存中有大量的空值的键

2、缓存击穿-请求量太大,缓存突然过期

缓存击穿是指一个key是一个热点key,在不停的扛着大量的并发,当缓存中的key在失效的瞬间,持续的大并发就会穿破缓存,直接请求到数据库。对数据库造成瞬间压力过大

解决方案:

第一种方案:热点数据永不过期

从缓存角度看,没有设置过期时间,就不会存在缓存过期之后产生的问题

第二种方案:加互斥锁

使用分布式锁,保证对每个key的访问同一时刻只能一个线程去查询后端服务,其他没有获取锁权限的线程则等待即可

3、缓存雪崩-在某一个时间段,缓存集中过期失效或者Redis宕机

对于数据库而言,所有请求压力会全部到达数据库,导致数据库调用量暴增,可能也造成数据库宕机的情况

解决方案:

第一种方案:Redis采用高可用

这种方案的思路就是讲数据在Redis中存放在服务器上,即使一个服务器挂掉,其他服务器还可以继续工作

第二种方案:限流降级

这种思路就是在缓存失效后,通过加锁或者队列来控制读取数据库的线程数量让线程在队列排队,控制整体请求速率

第三种方案:数据预热

数据预热及时在正是部署服务之前,先访问一遍数据,可以将大部分的数据加载到缓存中,在即将发生大并发之前已经加载不同的key,设置不同的过期时间,让缓存失效的时间更加均匀

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值