先操作数据库还是先操作缓存?

前言

在分布式系统中,缓存和数据库同时存在时,如果有写操作,先操作数据库还是先操作缓存呢?本文将分5种方案 展开阐述对比

缓存维护方案一

如果是一读(线程B)一写(线程A)操作, 「先操作缓存,再操作数据库」。流程图如下所示:
写的时候只负责删除缓存,读的时候负责写入缓存中
image.png

  1. 线程A发起一个写操作,第一步del cache

  2. 线程A第二步写入新数据到DB

  3. 线程B发起一个读操作,cache miss缓存失效了。

  4. 线程B从DB获取最新数据

  5. 线程B执行set cache,把从DB读到的数据,更新到缓存。

「这样看,没啥问题」。我们再看第二个流程图,如下:
image.png

  1. 线程A发起一个写操作,第一步del cache

  2. 此时线程B发起一个读操作,cache miss

  3. 线程B继续读DB,读出来一个老数据

  4. 然后老数据设置入cache

  5. 线程A写入DB最新的数据

OK,酱紫,就有问题了吧,老数据入到缓存了, 「每次读都是老数据啦,缓存与数据与数据库数据不一致了」。

缓存维护方案二

上个方案是一读一写,如果是双写操作, 「先操作缓存,在操作数据库」,会怎么样呢?
image.png

  1. 线程A发起一个写操作,第一步set cache

  2. 线程A第二步写入新数据到DB

  3. 线程B发起一个写操作,set cache

  4. 线程B第二步写入新数据到DB


「这样看,也没啥问题。」,但是有时候可能事与愿违,我们再看第二个流程图,如下:
image.png

  1. 线程A发起一个写操作,第一步set cache

  2. 线程B发起一个写操作,第一步set cache

  3. 线程B写入数据库到DB

  4. 线程A写入数据库到DB

执行完后,缓存保存的是B操作后的数据,数据库是A操作后的数据, 「缓存和数据库数据不一致了」。

缓存维护方案三

一写(线程A)一读(线程B)操作, 「先操作数据库,再操作缓存」。
image.png

  1. 线程A发起一个写操作,第一步write DB

  2. 线程A第二步del cache

  3. 线程B发起一个读操作,cache miss

  4. 线程B从DB获取最新数据

  5. 线程B同时set cache

有些朋友可能认为,在第2步删除缓存之前,线程B读过来呢?这时候,读到的是缓存老数据,这个可以认为是正常业务逻辑呀,下次再读取就是正确数据了。

这种方案「没有明显的并发问题」,但是呢, 「步骤二删除缓存失败」,还是个问题。不过概率比较小, 「优于方案一和方案二」,平时工作中也是使用方案三。

综上对比,我们一般采用方案三,但是有没有完美全解决方案三的弊端的方法呢?


缓存维护方案四

这个是方案三的改进方案,都是先操作数据库再操作缓存,我们来看一下流程图:

image.png

  • 通过数据库的 「binlog」来 「异步淘汰key」,以mysql为例 可以 「使用阿里的canal将binlog日志采集发送到MQ队列」里面,然后 「通过ACK机制 确认处理」这条更新消息,删除缓存,保证数据缓存一致性。

  • 但是呢还有个问题, 「如果是主从数据库呢」?

缓存维护方案五

主从DB问题:因为主从DB同步存在延时时间。如果删除缓存之后,数据同步到备库之前已经有请求过来时, 「会从备库中读到脏数据」,如何解决呢?解决方案如下流程图:
image.png

缓存维护总结

综上所述,在分布式系统中,缓存和数据库同时存在时,如果有写操作的时候, 「先操作数据库,再操作缓存」。如下:

1.读取缓存中是否有相关数据

2.如果缓存中有相关数据value,则返回

3.如果缓存中没有相关数据,则从数据库读取相关数据放入缓存中key->value,再返回

4.如果有更新写数据,则先操作数据库,再操作缓存

5.为了保证第四步更新缓存成功,使用binlog异步通知操作

6.如果是主从数据库,binglog取自于从库

7.如果是一主多从,每个从库都要采集binlog,然后消费端收到最后一台binlog数据才删

解决方案:

场景1

先删除cache,再更新DB,如果删除cache失败,就不更新DB。重试机制,删除cache。

场景2

利用消息队列,更新cache
DB产生新的增删改操作放入队列中,操作执行完发消息给cache,cache数据进行更新。如果中途出现查询,同步等待cache更新完成。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,402评论 6 499
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,377评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,483评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,165评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,176评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,146评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,032评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,896评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,311评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,536评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,696评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,413评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,008评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,815评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,698评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,592评论 2 353

推荐阅读更多精彩内容