java项目-延迟双删

延迟双删

java项目中,我们往往需要保证Redis缓存和数据库的一致性。
对于写操作,我们有两种解决方案

  1. 先删除缓存,后修改数据库
  2. 先修改数据库,后修改缓存
    其实这两种方案都会导致脏数据(缓存和数据库数据不一致的现象)的出现,所以我们需要一刀切的方式,直接先删除缓存,后修改数据库,延迟若干时间t,再次删除一次之前的缓存。我们称之为“延迟双删”
    在这里插入图片描述
    我们为什么要延迟时间t呢?原因是实际项目开发中我们的Redis往往是主从模式的,t时间过后,可以保证主节点有时间数据同步到从节点,然后再删除缓存,保证多个Redis节点都和数据库数据的一致性!!
    虽然“延迟双删”极大降低了脏数据的风险,但是依旧有脏数据的风险,因为延迟时间t很难有一个恰到好处的值,做不到绝对的强一致性!
    对于数据的一致性,有两种解决方案,一种是强一致性的解决方案,一种是最终一致性的解决方法,这取决于业务。一般来说普通业务选择最终一致性的就行了,这种性能最高。强一致性的性能低,需要使用分布式锁或者是读锁+排他锁(read-lock+write-lock),其中读锁是可以高并发读取,排他锁排斥读锁与其他排他锁

强一致性

如果我们想要强一致性,我们可以添加一个分布式锁,但是此时性能会降低很多!
分布式锁方案如下:
直接保证了线程之间按照串行化的流程执行!但是像这种分布式锁会导致读写都添加了锁,因此性能特别低。
Alt

下面这种是先删除缓存,后更新数据库的翻车场景
Alt
下面这种是先更新数据库,后删除缓存的翻车场景,1的情况是线程1来查询缓存的时候,恰逢Key过期了,没查到,就访问数据库,接着线程2来更新数据库了,然后删除cache,最后线程1写入缓存(步骤4)
Alt
那么我们如何针对分布式锁这种读和写都添加锁的性能问题进行优化呢?
我们可以使用共享锁和排他锁,共享锁是读锁,其他线程可以读,排他锁是读写锁,使用排他锁的时候其他线程无法读或者写,都禁止了!
Alt
读锁,可读,不可写
在这里插入图片描述
写锁,其他线程无法读和写
在这里插入图片描述
强一致的解决方案,就是读写锁。就是上面介绍的那些

最终一致性

下面开始介绍最终一致性的解决方案:

1.MQ保证最终一致性

由MQ保证最后更新缓存的时刻。流程是这样的:
修改数据请求到达item-Service,然后写入到MySQL,接着item-Service发布消息到MQ,cache-Service监听消息,如果cache-Service接受到消息了,就会及时去更新缓存。这个过程的可靠性由MQ维持

在这里插入图片描述

2.canal保证的最终一致性

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hwg985

祝老板生意兴隆,财源广进

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

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

打赏作者

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

抵扣说明:

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

余额充值