Redis双写一致性问题

1、缓存的最终一致性

从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案。这种方案下,我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可。也就是说如果数据库写成功,缓存更新失败,那么只要到达过期时间,则后面的读请求自然会从数据库中读取新值然后回填缓存。因此,接下来讨论的思路不依赖于给缓存设置过期时间这个方案。

2、数据更新策略

(1)先更新数据库,再更新缓存(不可行)

在这里插入图片描述

存在问题:1)当写操作十分频繁的情况下,可能用户根本就没有去读缓存数据就又频繁更新了,无疑是浪费性能的。
2)如果你的数据并不是直接写入缓存的,而是经过一系列计算再存入数据库的,那么频繁更新缓存同时还浪费了主业务服务器的性能。
3)极容易造成数据不一致情况

(2)先删除缓存,再更新数据库(推荐)

在这里插入图片描述
伪代码

public void write(String key,Object data){
	redis.delKey(key);
	db.updateData(data);
	Thread.sleep(1000);
	redis.delKey(key);
}

为了解决上述问题,采用延时双删策略,就是在更新完数据库后,睡眠一定时间,再次进行删除。
为什么要延时?
在这里插入图片描述
假设一个场景:Redis缓存中并没有这个数据,而在更新这个数据时,有个查询请求进来了,这个请求查取到旧的数据放入内存中,但是还没有写入到redis中,这是更新已经完成,且执行了第二次redis缓存删除,之后内存的旧数据被写入到了redis中,造成了redis和数据库数据不一致。
所以需要延时从内存写入redis缓存的时间,如果数据库做了读写分离,还需要缓存从主库同步到从库的时间。
吞吐量降低? 我们可以将第二次删除作为异步的。自己起一个线程,异步删除。这样,写的请求就不用沉睡一段时间后了,再返回。这么做,加大吞吐量。

(3)先更新数据库,再删除缓存

这种方案看上诉为什么要延时? 图解,如果redis中缓存正好过期,则可能会发生上图情况,此时我们也可以用延时来解决问题。
与(2)不同的是,(3)方案不会先去删除redis中缓存,如果缓存在正好过期,相当于先删除了redis缓存,就会存在上述的数据不一致问题,同样用延时删除解决。

(2)(3)方案中如果删除缓存失败怎么办? 删除失败,利用消息队列实现重试,设置重试次数,如果一直失败,只能靠redis的过期机制达到最终一致性。这里的删除最好是自己起一个线程,异步删除,保证业务不阻塞,正常运行。
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值