「微服务」缓存、数据库双写一致性

前言

缓存由于高并发和高性能的特性,在当前的主流架构中基本上属于必须的其中一个高并发支撑模块。缓存在使用时,读流程基本保持一致的认知,不存在其他异议。流程如下:

image

缓存读流程

但是,在写流程上,由于需要同时将数据写入数据库与缓存中,就一定涉及到缓存与数据库数据双写,数据一致性的问题。所以,在系统的设计上,需要考虑如何处理数据一致性问题。

一般来说,在引入缓存机制的同时也牺牲了一定的一致性,缓存数据与数据库数据是允许在一定时间窗口之间内的非一致性。如果必须保持一致的话,那么缓存的引入基本上没有意义了。必须保证强一致的话,就只能使用读请求和写请求串行化,串到一个内存队列里去。但是它也会导致系统的吞吐量大幅度降低,用比正常情况下多几倍的机器去支撑线上的一个请求。

常用双写模式解析

#先更新数据库,再删除缓存(Cache Aside)

Facebook使用的方式,也是推荐的使用方式。包括:

  • 失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中;* 命中:应用程序从cache中取数据,取到后返回;* 更新:先把数据存到数据库中,成功后,再让缓存失效;
image

采用CacheAside模式的问题在于,在读写线程同时并发,且满足

  1. 读线程读取缓存时,缓存正好失效
  2. 读线程读数据库数据
  3. 写线程更新数据库
  4. 写线程删除缓存
  5. 读线程将查询到的数据写入缓存

以上所有查件时,在理论上来说,确实可能会产生脏数据。但是实际上出现的概念极低。

image

首先,需要满足读缓存时缓存失效,并且存在并发写。在实际上,数据库的写操作完比读操作慢得多,而且还需要锁表,而读操作必须在写操作前进入数据库操作,而又晚于写操作更新缓存,所有条件具备的概率太低,基本上忽略。

#先删除缓存,再更新数据库

image

先更新数据库,再删除缓存区别只是切换了执行的顺序。但是,该方式会导致大概率的不一致性发生。

  1. 写线程更新数据,删除缓存
  2. 读线程查询缓存数据,发现没有缓存数据
  3. 读线程读数据库数据
  4. 写线程更新数据库
  5. 读线程将查询到的数据写入缓存
image

解决方案:采用双删机制。删除缓存 > 更新数据库 > 休眠一点时间 > 再次删除缓存。

但是该方案不采纳。休眠时间无法评估,而且大大降低了系统吞吐。

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

该方案是不能被采用的方案。

image

如上图所示,写线程A和线程B同时更新数据,但是线程B早于线程A更新缓存,导致数据不一致。

除此之外,缓存数据可能是多纬度的计算数据而不仅仅只是单一的某个数据。如某缓存数据由A表,B表,C表多表数据计算而成,那么缓存的更新因素就非常多的,而且要更新缓存,需要额外的查询其他表数据。

删除缓存是一种懒计算,在需要的时候才去重新计算。

推荐使用模式

在上述的模式中,推荐采用先更新数据库,再删除缓存(Cache Aside)模式。

但是存在一个问题,如果删除缓存的时候失败了如何处理?

在生产中,缓存的使用依赖于抽象缓存接口,根据允许的数据差异时间窗口和业务,采用的是针对实际缓存进行包装,提供删除重试机制,业务层不需要额外关注删除问题,避免了业务侵入。

重试机制采用的是本地重试。 根据配置的重试上限进行重试,达到上限无法删除成功抛出异常到上层。上层业务决定是否回滚修改,继续向上抛出异常,然后业务调用者的重试机制重新尝试。还是忽略该失败。

正常情况下,由于缓存本身影响的一致性导致数据一定存在一定时间窗口的差异。如果缓存在特定某一时刻无法删除,正常情况下不会影响业务,这是被允许的情况(缓存的数据必须有过期时间,而且时间不能太久,根据业务设置合理过期时长是非常重要的)。如果出现批量的失败,可能是缓存系统异常或者业务系统异常都会被监控系统探测到(监控系统很重要),此时已经不是某个业务或服务的问题,而是整个系统问题。

当然,如果非要强制一定要执行成功,建议方案使用MQ进行异步化。

image

总结

缓存的使用时双写是无法很好的保证一致性的,在使用缓存时就应该接受这一点,而不是强求一致性,导致系统或者业务变得非常复杂。

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

推荐阅读更多精彩内容