请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

缓存并发更新顺序的问题

之前面试,有被问到,缓存更新的顺序是什么,先更新数据库,还是先删除缓存。

老师能具体讲一下吗。

正在回答

1回答

Jimin 2018-08-30 23:06:26

你好,这个问题,很难找到一种方案能适用于所有的场景,否则早就会一些组件封装出来使用了,而且数据一致性也是所有分布式系统都很难从根本解决的问题,cap原理就放在那,谁都躲不开。

但实际这个问题确实存在,面试也会问到,其实关键还是考察你是否能根据不同的场景做特定的分析,也看看是否你能给出一些可行的方案。这里说一些手段,你可以感受一下:

1、更新数据库,异步更新缓存,如果失败,可以选择放入消息队列去更新或删除掉

2、先更新缓存,如果失败,可以选择放入消息队列去更新或删除掉,再更新数据库。如果数据库更新失败,删除缓存(依旧可以通过多种手段保证删除成功)

这两点都是通过异步或消息队列的方式保证数据最终一致性,但是需要注意的是,先删除缓存出错时,不能影响主流程数据库更新的操作,本质上缓存是否更新失败都要保证数据库更新进行操作。因此呢,我个人更喜欢先更新数据库,然后借助消息队列等保证缓存里数据和db里的一致,甚至删除缓存保证数据正确。

3、可以在缓存中考虑加入标记位,先更新缓存时,可以先置标记位为失效状态,等db更新后,再更新缓存数据,并更新标记位为有效。当使用缓存时,记得check标记位就可以了。

实际中出现这种问题的概率很小,毕竟那些缓存的组件,比如redis,性能都特别好,因此在实际中,我们都默认按照他会成功去处理,然后捕捉住异常,做些补偿性手段,来保证最终的一致性。其实,也没有什么完美的方案,适合自己的场景,代价最小的,就是最好的~


1 回复 有任何疑惑可以回复我~
  • 提问者 zhusx #1
    老师我觉得缓存采用淘汰策略好一点吧,更新的话感觉会有问题,像你说的第一点(先不考虑失败的情况):更新数据库,异步更新缓存,如果失败,可以选择放入消息队列去更新或删除掉
    
    假如T1和T2线程同时做更新一个字段的操作,此时数据库和缓存的值都是1,T1设置该字段为2,T2设置该字段为3,执行顺序是:
    T1更新db //db为2
    T2更新db //db为3
    T2更新缓存 //缓存为3
    T1更新缓存 //缓存为2
    这样就导致了数据库和缓存不一致的问题。采用删除的话,T1,T2同时删除也不会有问题。
    回复 有任何疑惑可以回复我~ 2018-08-31 11:41:01
  • Jimin 回复 提问者 zhusx #2
    嗯,理论上淘汰更保险一点。但是,很多时候还是希望缓存能有,挡住请求打到数据库。淘汰缓存也容易一些
    回复 有任何疑惑可以回复我~ 2018-08-31 12:06:19
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信