Redis双写一致性

双写一致性

当修改了数据库的数据也要同时更新缓存的数据,缓存和数据库的数据要保持一致。

注意这里是对数据库进行写操作而不是读操作,通常我们有两种方式完成这个写操作,分别是:先删除缓存再修改数据库 和 先修改数据库再删除缓存,但是这两种方式都存在问题(出现脏数据)。

先删除缓存再修改数据库:

先删除缓存再修改数据库的话,如果在 线程1 删除缓存后有 线程2 对数据进行了查询(此时数据库中的数据仍然是旧数据,且缓存中已经没有数据)并将查询的值写入缓存,那么缓存中存放的就是旧数据,此时 线程1 也完成了对数据库的更新,那么就会出现数据库是新数据而缓存是旧数据的情况。

先修改数据库再删除缓存:

我们这里讨论一种特殊情况,就是缓存中的数据过期了,此时 线程1 去查缓存查不到,就会去访问数据库(此时数据库是旧数据),突然 线程2 横插一脚,它来执行了一个更新数据库的操作,把数据库的数据更新为了新数据,并去删除缓存(虽然缓存中没有数据,不过不影响),线程2 执行完毕后 线程1 继续执行,把它访问数据库(旧数据)的数据更新到缓存中,这样就出现了缓存是旧数据而数据库是新数据的情况。

为了减少脏数据的出现,我们可以使用下面这种方法

延迟双删:

在删除缓存、修改数据库后再次进行一次缓存删除,注意要延时(因为数据库也可能有子节点,需要给时间给主从节点的数据同步),不过延时的时间并不能确定,所以依然有脏数据出现的可能,但是也已经极大的控制了这个可能性。

如果我们的系统有强一致性的要求,就需要使用分布式锁来实现了

分布式锁:

这种方法呢就保证了强一致性,但是性能较差,我们可以用读写锁(ReadWriteLock)优化一下

共享锁readLock,只限制写操作,加了这个锁后不影响别人的读操作(读操作时添加,读读不互斥,读写互斥)

独占锁writeLock,读写都影响(写操作时添加)

毕竟是加锁,其实这种方法的性能也是不高,不过保证了强一致性,在我们对强一致性要求不高(也许延迟一致的时候),可以使用下面两种异步通知的方法。

基于MQ的异步通知:

基于Canal的异步通知:

这种方法更好一点,canal会伪装成mysql的一个从节点,不会对代码进行侵入。

两种异步通知的方法当然都是存在短暂的延迟的,不能保证强一致性,都是最终数据都会变成一致的,我们可以按需选择自己的方法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dak2n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值