码迷,mamicode.com
首页 > 数据库 > 详细

先更新缓存还是先更新数据库

时间:2020-06-26 21:50:54      阅读:143      评论:0      收藏:0      [点我收藏+]

标签:脏数据   container   des   div   image   最新   lazy   value   pattern   

概览

说这个问题之前得看下几种缓存模式,可以先看下缓存模式(Caching Aside、Read Through、Write Through、Write Behind)这篇文章。

先更新缓存,再更新数据库

考虑两个并发操作:线程A写,线程B读

技术图片

  • 1、线程A发起一个写操作,第一步delete cache
  • 2、此时线程B发起一个读操作,cache miss
  • 3、线程B继续读数据库,读出来一个老数据
  • 4、然后老数据入cache
  • 5、线程A写入了最新的数据

这样以后每次从缓存中读到的都是老数据,数据不一致,不能满足我们的需求。

既然这种情况下先删除缓存会有数据不一致的情况,那我们来试试第一步不删除缓存而是直接更新缓存试试看。

考虑两个并发操作:线程A写,线程B写

技术图片

  • 1、线程A发起一个写操作,第一步set cache
  • 2、线程B发起一个写操作,第一步set cache
  • 3、线程B写入数据到数据库
  • 4、线程A写入数据到数据库

这样以后每次从缓存中读到的都是线程B设置数据,但数据库中存储的是线程A写入的数据,导致数据不一致。

先更新数据库,再更新缓存

考虑两个并发操作:线程A写,线程B读

技术图片

  • 1、线程A发起一个写操作,第一步写入数据到数据库
  • 2、线程A第二步delete cache
  • 3、线程B发起一个读操作,cache miss
  • 4、线程B从数据库获取最新数据
  • 5、线程B同时set cache

注意我们的更新是先更新数据库,成功后,让缓存失效。

一个是查询操作,一个是更新操作的并发,首先,没有了文章开始删除cache数据的操作了,而是先更新了数据库中的数据,此时,缓存依然有效,所以,并发的查询操作拿的是没有更新的数据,但是,更新操作马上让缓存的失效了,后续的查询操作再把数据从数据库中拉出来。而不会像文章开头的那个逻辑产生的问题,后续的查询操作一直都在取老的数据。

这是标准的design pattern,包括Facebook的论文《Scaling Memcache at Facebook》也使用了这个策略。为什么不是写完数据库后更新缓存?你可以看一下Quora上的这个问答《Why does Facebook use delete to remove the key-value pair in Memcached instead of updating the Memcached during write request to the backend?》,主要是怕两个并发的写操作导致脏数据,这个问题我们下面会说到。

考虑两个并发操作:线程A写,线程B写

  • 1、线程A发起一个写操作,第一步写入数据到数据库
  • 2、线程B发起一个写操作,第一步写入数据到数据库
  • 3、线程B第二步delete cache
  • 4、线程A第二步delete cache

该情况下由于线程A、B最初都把数据写入了数据库,接着都有delete cache,此时如果有线程C来读数据,都会从数据库中查询最新的数据并set cache。

为什么最后是把缓存的数据删掉,而不是把更新的数据写到缓存里。这么做引发的问题是,如果A,B两个线程同时做数据更新,A先更新了数据库,B后更新数据库,则此时数据库里存的是B的数据。而更新缓存的时候,是B先更新了缓存,而A后更新了缓存,则缓存里是A的数据。这样缓存和数据库的数据也不一致。

先更新缓存还是先更新数据库

标签:脏数据   container   des   div   image   最新   lazy   value   pattern   

原文地址:https://www.cnblogs.com/mrcharleshu/p/13196386.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!