缓存数据一致性

提出问题:在使用美团Squirrel 作为分布式缓存 ,那么缓存与数据库的一致性如何保证?如何尽可能拿到最新数据?(以单节点为例)

方案1:先更新数据库后更新缓存​不推荐

分析缺点:
(1)AB两个线程写。A更新数据库->B更新数据库->B更新缓存->A更新缓存 显然出现了数据覆盖,此时数据不一致,是旧数据。

(2)另外在更新数据库的时候还需要更新缓存,如果更新逻辑复杂,导致整个更新周期很长。

解决方案:
对于(1)可以增加版本号,版本号比目前大的才更新。

对于(2)可以考虑任务异步化。

方案2:先删除缓存 再更新数据库

分析缺点:
(1) A 先写B后读。那可能存在这样的序列:A删除缓存->B未命中读数据库后,将其加入缓存->A更新数据库 此时数据发生不一致。

解决办法:
“延迟双删”可以解决,在A线程写入完成之后 ,过M时间再去删除缓存,M时间的大小需要根据B线程将数据库数据放入缓存的时间N 来定,比其稍大即可。

方案3:先更新数据库再删除缓存​推荐

分析缺点:
(1)A 先写B后读。假设存在 A先更新数据库->B读->A删除缓存。这样B读到的是过期数据 但是这是可以忍受的,因为这只是短暂的不一致后续的读都是一致数据。

(2)假设某时刻缓存恰好失效,B线程先读,A线程后写。可能存在这样的操作序列B 读数据库->A更新数据库->A 加入缓存->B加入缓存 此时旧值就会覆盖最新值。其实这种情况发生的比较少,因为读操作应该比数据库更新操作快,所以B加入缓存的这一步很大可能是在A 更新数据库之前的操作。

关于删除缓存失败的解决办法?

我们知道不管是延时双删还是一次删除,那么删除失败那么意味着可能发生数据不一致,所以应该循环重试直到成功。

方案1:使用消息队列,在业务代码中应该在更新数据库之后,在将删除任务发到消息队列中,然后正确消费就可以。

方案2:同样适用消息队列,但是利用binlog,我们知道binlog记录改变数据库的操作,所以写操作会被记录,当其变化时就去产生任务放到队列中,减少了业务代码的侵入。比较推荐。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值