数据库和缓存的数据一致性问题

系统使用缓存的方式是复制数据库中的部分数据到缓存中,然后就可以从缓存中更快地获取数据。但是数据不仅仅有读操作,有时候也需要进行写操作。完成数据写之后,再次使用缓存的时候,需要保证从缓存中读取到的数据是最新的,即保证缓存一致性

为了保证数据最新,必然要对数据库和缓存都进行更新,这就涉及到两个问题:

  1. 更新缓存的时候,是修改缓存数据还是直接删除缓存?
  2. 数据库和缓存先更新哪一个?

先简单分析一下

淘汰缓存:

优点:操作简单,没有复杂的逻辑;

缺点:下一次读取,会带来额外的miss

更新缓存:

优点:下一次直接hit

缺点:可能的额外开销

以上方案排列组合一下共有四种方式:

  1. 先删除缓存,再更新数据库
  2. 先更新缓存,再更新数据库
  3. 先更新数据库,再删除缓存
  4. 先更新数据库,再更新缓存

理想情况下,四种方式都是可行的,并且删除缓存会带来一次可能的cache miss,从这个角度来看24更优。

但是一个鲁棒的系统,需要关注到那些“不理想”的异常情况:

异常一:更新缓存带来的数据不一致

当更新数据库之后,更新缓存之前,有一个并发的读操作,就会从缓存中读到脏数据。从这个角度来看删除缓存也会有这个问题,所以先对缓存操作会更好一点。

但是如果先删除缓存,仍然可能出现:在删除缓存之后,更新数据库之前,执行读操作。由于更新需要一读一写,会更慢,导致新的缓存仍然是旧数据。

异常二:并发操作带来的数据不一致

两个线程同时更新数据,隐含两个问题:

  1. ABBA或BAAB带来缓存不一致,删除缓存能解决这一问题
  2. 最终结果并非是后执行的更新的数据。和更新顺序无关,需要保证串行执行指令。

异常三:后执行的更新出错被强行终止

先更新缓存能保证后续读取到正确的数据,但是这样数据库中会保留错误数据。

先删除缓存的代价是一次miss+错误数据

后更新缓存/删除缓存会一直读取错误数据(由于操作失败)

上述问题没有完美的解决方案,最好设置一个异常检测来确保正常更新。

总结

根据上面的分析,删除缓存以较小的代价解决了数据不一致的问题,但是先执行还是后执行则各有优劣:

  1. 先淘汰缓存

删除缓存后,肯定后续还要更新缓存

同步更新:读写数据的时候再更新缓存

异步更新:更新数据库后立即异步更新缓存

如果是同步更新缓存,在完成数据库更新前,会有一大段时间读取到脏数据

如果是异步更新缓存,可以保证一致性,但是在数据库更新完成之前,不存在缓存,每次都需要从数据库中读取,读的效率不高。

适合需要确保数据一致性的需求下使用

  1. 后淘汰缓存

更新数据库期间,会有一段时间数据不一致,但是读的效率很好。

适合追求效率,但是对数据一致性要求没那么高的需求下使用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值