本文主要讨论这么几个问题:

(1)数据库主从延时为何会导致缓存数据不一致

(2)优化思路与方案

一、需求缘起

上一篇《缓存架构设计细节二三事》中有一个小优化点,在只有主库时,通过“串行化”的思路可以解决缓存与数据库中数据不一致。引发大家热烈讨论的点是“在主从同步,读写分离的数据库架构下,有可能出现脏数据入缓存的情况,此时串行化方案不再适用了”,这就是本文要讨论的主题。

二、为什么数据会不一致

为什么会读到脏数据,有这么几种情况:

(1)单库情况下,服务层的并发读写,缓存与数据库的操作交叉进行


虽然只有一个DB,在上述诡异异常时序下,也可能脏数据入缓存:

1)请求A发起一个写操作,第一步淘汰了cache,然后这个请求因为各种原因在服务层卡住了(进行大量的业务逻辑计算,例如计算了1秒钟),如上图步骤1

2)请求B发起一个读操作,读cache,cache miss,如上图步骤2

3)请求B继续读DB,读出来一个脏数据,然后脏数据入cache,如上图步骤3

4)请求A卡了很久后终于写数据库了,写入了最新的数据,如上图步骤4

这种情况虽然少见,但理论上是存在的, 后发起的请求B在先发起的请求A中间完成了。

(2)主从同步,读写分离的情况下,读从库读到旧数据

在数据库架构做了一主多从,读写分离时,更多的脏数据入缓存是下面这种情况:


1)请求A发起一个写操作,第一步淘汰了cache,如上图步骤1

2)请求A写数据库了,写入了最新的数据,如上图步骤2

3)请求B发起一个读操作,读cache,cache miss,如上图步骤3

4)请求B继续读DB,读的是从库,此时主从同步还没有完成,读出来一个脏数据,然后脏数据入cache,如上图步4

5)最后数据库的主从同步完成了,如上图步骤5

这种情况请求A和请求B的时序是完全没有问题的,是主动同步的时延(假设延时1秒钟)中间有读请求读从库读到脏数据导致的不一致。

那怎么来进行优化呢?

三、不一致优化思路

有同学说“那能不能先操作数据库,再淘汰缓存”,这个是不行的,在《缓存和数据库先操作谁》的文章中介绍过。

出现不一致的根本原因:

(1)单库情况下,服务层在进行1s的逻辑计算过程中,可能读到旧数据入缓存

(2)主从库+读写分离情况下,在1s钟主从同步延时过程中,可能读到旧数据入缓存

既然旧数据就是在那1s的间隙中入缓存的,是不是可以在写请求完成后,再休眠1s,再次淘汰缓存,就能将这1s内写入的脏数据再次淘汰掉呢?

答案是可以的。

写请求的步骤由2步升级为3步:

(1)先淘汰缓存

(2)再写数据库(这两步和原来一样)

(3)休眠1秒,再次淘汰缓存

这样的话,1秒内有脏数据如缓存,也会被再次淘汰掉,但带来的问题是:

(1)所有的写请求都阻塞了1秒,大大降低了写请求的吞吐量,增长了处理时间,业务上是接受不了的

再次分析,其实第二次淘汰缓存是“为了保证缓存一致”而做的操作,而不是“业务要求”,所以其实无需等待,用一个异步的timer,或者利用消息总线异步的来做这个事情即可


写请求由2步升级为2.5步:

(1)先淘汰缓存

(2)再写数据库(这两步和原来一样)

(2.5)不再休眠1s,而是往消息总线esb发送一个消息,发送完成之后马上就能返回

这样的话,写请求的处理时间几乎没有增加,这个方法淘汰了缓存两次,因此被称为“缓存双淘汰”法。这个方法付出的代价是,缓存会增加1次cache miss(代价几乎可以忽略)。

而在下游,有一个异步淘汰缓存的消费者,在接收到消息之后,asy-expire在1s之后淘汰缓存。这样,即使1s内有脏数据入缓存,也有机会再次被淘汰掉。

上述方案有一个缺点,需要业务线的写操作增加一个步骤,有没有方案对业务线的代码没有任何入侵呢,是有的,这个方案在《细聊冗余表数据一致性》中也提到过,通过分析线下的binlog来异步淘汰缓存:


业务线的代码就不需要动了,新增一个线下的读binlog的异步淘汰模块,读取到binlog中的数据,异步的淘汰缓存。

提问:为什么上文总是说1s,这个1s是怎么来的?

回答:1s只是一个举例,需要根据业务的数据量与并发量,观察主从同步的时延来设定这个值。例如主从同步的时延为200ms,这个异步淘汰cache设置为258ms就是OK的。

四、总结

在“异常时序”或者“读从库”导致脏数据入缓存时,可以用二次异步淘汰的“缓存双淘汰”法来解决缓存与数据库中数据不一致的问题,具体实施至少有三种方案:

(1)timer异步淘汰(本文没有细讲,本质就是起个线程专门异步二次淘汰缓存)

(2)总线异步淘汰

(3)读binlog异步淘汰

【文章转载自微信公众号“架构师之路”】

【58沈剑架构系列】主从DB与cache一致性的更多相关文章

  1. 【58沈剑架构系列】DB主从一致性架构优化4种方法

    需求缘起 大部分互联网的业务都是“读多写少”的场景,数据库层面,读性能往往成为瓶颈.如下图:业界通常采用“一主多从,读写分离,冗余多个读库”的数据库架构来提升数据库的读性能. 这种架构的一个潜在缺点是 ...

  2. 【58沈剑架构系列】mysql并行复制优化思路

    一.缘起 mysql主从复制,读写分离是互联网用的非常多的mysql架构,主从复制最令人诟病的地方就是,在数据量较大并发量较大的场景下,主从延时会比较严重. 为什么mysql主从延时这么大? 回答:从 ...

  3. 【58沈剑架构系列】RPC-client异步收发核心细节?

    第一章聊了[“为什么要进行服务化,服务化究竟解决什么问题”] 第二章聊了[“微服务的服务粒度选型”] 第三章聊了[“为什么说要搞定微服务架构,先搞定RPC框架?”] 上一章聊了[“微服务架构之RPC- ...

  4. 【58沈剑架构系列】互联网公司为啥不使用mysql分区表?

    缘起:有个朋友问我分区表在58的应用,我回答不出来,在我印象中,百度.58都没有听说有分区表相关的应用,业内进行一些技术交流的时候也更多的是自己分库分表,而不是使用分区表.于是去网上查了一下,并询问了 ...

  5. 【58沈剑架构系列】lvs为何不能完全替代DNS轮询

    上一篇文章“一分钟了解负载均衡的一切”引起了不少同学的关注,评论中大家争论的比较多的一个技术点是接入层负载均衡技术,部分同学持这样的观点: 1)nginx前端加入lvs和keepalived可以替代“ ...

  6. 【58沈剑架构系列】微服务架构之RPC-client序列化细节

    第一章聊了[“为什么要进行服务化,服务化究竟解决什么问题”] 第二章聊了[“微服务的服务粒度选型”] 上一篇聊了[“为什么说要搞定微服务架构,先搞定RPC框架?”] 通过上篇文章的介绍,知道了要实施微 ...

  7. 【58沈剑架构系列】为什么说要搞定微服务架构,先搞定RPC框架?

    第一章聊了[“为什么要进行服务化,服务化究竟解决什么问题”] 第二章聊了[“微服务的服务粒度选型”] 今天开始聊一些微服务的实践,第一块,RPC框架的原理及实践,为什么说要搞定微服务架构,先搞定RPC ...

  8. 【58沈剑架构系列】细聊分布式ID生成方法

    一.需求缘起 几乎所有的业务系统,都有生成一个记录标识的需求,例如: (1)消息标识:message-id (2)订单标识:order-id (3)帖子标识:tiezi-id 这个记录标识往往就是数据 ...

  9. KA,连接池居然这么简单? 原创: 58沈剑 架构师之路 3月20日

    KA,连接池居然这么简单? 原创: 58沈剑 架构师之路 3月20日

随机推荐

  1. phonegap(cordova)从手机app跳转到web页面在跳转回APP本地页面思路

    项目中需要用到 WAP支付宝支付. 但是 使用PHONEGAP开发 跳转到支付宝支付,然后跳转回来 就回不到APP的本地页面, 就是使用WAP的第三方登录也是一样的.很难从WAP页面在跳转到 app本 ...

  2. array_uintersect、array_uintersect_assoc、array_uintersect_uassoc 的使用方法

    和 array_intersect 类似,只不过 array_uintersect* 系列函数的值比较使用自定义函数: 键的比较,array_uintersect.array_uintersect_a ...

  3. jsp 文件无法加载 css、js 的问题

    今天遇到一个问题是,在 jsp 里面引入 css.js,请求的状态是 200,但 css.js 的内容却是空的. 这是因为 servlet 有个 url-pattern,将 css.js 的路径当做 ...

  4. [LeetCode] 数学计算模拟类问题:加法,除法和幂,注意越界问题。题 剑指Offer,Pow(x, n) ,Divide Two Integers

    引言 数学计算的模拟类题目,往往是要求实现某种计算(比如两数相除),实现的过程中会有所限定,比如不允许乘法等等. 这类题目首先要注意计算过程中本身的特殊情况.比如求相除,则必须首先反映过来除数不能为0 ...

  5. 跟我一起写Makefile(三)

    书写规则———— 规则包含两个部分,一个是依赖关系,一个是生成目标的方法. 在Makefile中,规则的顺序是很重要的,因为,Makefile中只应该有一个最终目标,其它的目标都是被这个目标所连带出来 ...

  6. 跟我一起写Makefile(二)

    Makefile 总述——————— 一.Makefile里有什么? Makefile里主要包含了五个东西:显式规则.隐晦规则.变量定义.文件指示和注释. 1.显式规则.显式规则说明了,如何生成一个或 ...

  7. z-index详细攻略

    概念 z-index 属性设置元素的堆叠顺序.拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面. 层级关系的比较 1. 对于同级元素,默认(或position:static)情况下文档流后面的 ...

  8. CF844 C 置换 水

    由于每个数字只出现一次,离散化一下,置换求个循环节就好了. /** @Date : 2017-08-25 01:39:39 * @FileName: C.cpp * @Platform: Window ...

  9. Flask---使用Bootstrap新建第一个demo

    Flask---使用Bootstrap新建第一个demo 参考自http://www.jianshu.com/p/417bcbad82fb 还有<Flask web开发> 前端用到Boot ...

  10. 2017ACM暑期多校联合训练 - Team 5 1006 HDU 5205 Rikka with Graph (找规律)

    题目链接 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, s ...