美团二面 Redis与MySQL双写分歧性如何保障

前言

大家好,我是田螺。有位星球粉丝去美团面试。他说,被问到Redis与MySQL双写分歧性如何保障?

这道题其实就是在问缓存和数据库在双写场景下,分歧性是如何保障的?本文将跟大家一同来讨论如何回答这个疑问。

谈谈分歧性

分歧性就是数据坚持分歧,在散布式系统中,可以了解为多个节点中数据的值是分歧的。

三个经典的缓存形式

缓存可以优化功能、缓解数据库压力,但是经常使用缓存也会造成数据不分歧性的疑问。普通咱们是如何经常使用缓存呢?有三种经典的缓存经常使用形式:

Cache-Aside Pattern

Cache-Aside Pattern,即旁路缓存形式,它的提出是为了尽或者地处置缓存与数据库的数据不分歧疑问。

Cache-Aside读流程

Cache-Aside Pattern的读恳求流程如下:

Cache-Aside读恳求

Cache-Aside 写流程

Cache-Aside Pattern的写恳求流程如下:

Cache-Aside写恳求

降级的时刻,先降级数据库,而后再删除缓存。

Read-Through/Write-Through(读写穿透)

Read/Write-Through形式中,服务端把缓存作为关键数据存储。运行程序跟数据库缓存交互,都是经过形象缓存层成功的。

Read-Through

Read-Through的简明流程如下:

Read-Through简明流程

这个简明流程是不是跟Cache-Aside很像呢?其实Read-Through就是多了一层Cache-Provider而已,流程如下:

Read-Through实践只是在Cache-Aside之上启动了一层封装,它会让程序代码变得更繁复,同时也缩小数据源上的负载。

Write-Through

Write-Through形式下,当出现写恳求时,也是由缓存形象层成功数据源缓和存数据的降级,流程如下:

Write-behind (异步缓存写入)

Write-behind跟Read-Through/Write-Through有相似的中央,都是由Cache Provider来担任缓存和数据库的读写。它们又有个很大的不同:Read/Write-Through是同步降级缓存和数据的,Write-Behind则是只降级缓存,不间接降级数据库,经过批量异步的形式来降级数据库。

这种形式下,缓存和数据库的分歧性不强,对分歧性要求高的系统要审慎经常使用。但是它适宜频繁写的场景,MySQL的InnoDB Buffer Pool机制就经常使用到这种形式。

操作缓存的时刻,究竟是删除缓存呢,还是降级缓存?

日常开发中,咱们普通经常使用的就是Cache-Aside形式。有些小同伴或者会问,Cache-Aside在写入恳求的时刻,为什么是删除缓存而不是降级缓存呢?

咱们在操作缓存的时刻,究竟应该删除缓存还是降级缓存呢?咱们先来看个例子:

这时刻,缓存保留的是A的数据(老数据),数据库保留的是B的数据(新数据),数据不分歧了,脏数据出现啦。假设是删除缓存取代降级缓存则不会出现这个脏数据疑问。

降级缓存相关于删除缓存,还有两点劣势:

双写的状况下,先操作数据库还是先操作缓存?

Cache-Aside缓存形式中,有些小同伴还是会有不懂,在写恳求上来的时刻,为什么是先操作数据库呢?为什么不先操作缓存呢?

假定有A、B两个恳求,恳求A做降级操作,恳求B做查问读取操作。

酱紫就有疑问啦,缓存和数据库的数据不分歧了。缓存保留的是老数据,数据库保留的是新数据。因此,Cache-Aside缓存形式,选用了先操作数据库而不是先操作缓存。

数据库缓和存数据坚持强分歧,可以嘛?

实践上,没方法做到数据库与缓存相对的分歧性。

其实,这是由CAP通常选择的。缓存系统实用的场景就是非强分歧性的场景,它属于CAP中的AP。团体感觉,谋求相对分歧性的业务场景,不适宜引入缓存。

CAP通常,指的是在一个散布式系统中, Consistency(分歧性)、 Availability(可用性)、Partition tolerance(分区容错性),三者无法得兼。

但是,经过一些打算优化处置,是可以保障弱分歧性,最终分歧性的。

3种打算保障数据库与缓存的分歧性

缓存延时双删

有些小同伴或者会说,并不必定要先操作数据库呀,驳回缓存延时双删战略,就可以保障数据的分歧性啦。什么是延时双删呢?

延时双删流程

这个休眠一会,普通多久呢?都是1秒?

这个休眠时期 = 读业务逻辑数据的耗时 + 几百毫秒。为了确保读恳求完结,写恳求可以删除读恳求或者带来的缓存脏数据。

这种打算还算可以,只要休眠那一会(比如就那1秒),或者有脏数据,普通业务也会接受的。但是假设第二次删除缓存失败呢?缓存和数据库的数据还是或者不分歧,对吧?给Key设置一团体造的expire过时时期,让它智能过时怎么?那业务要接受过时时期内,数据的不分歧咯?还是有其余更佳打算呢?

删除缓存重试机制

不论是延时双删还是Cache-Aside的先操作数据库再删除缓存,都或者会存在第二步的删除缓存失败,造成的数据不分歧疑问。可以经常使用这个打算优化:删除失败就多删除几次呀,保障删除缓存成功就可以了呀~ 所以可以引入删除缓存重试机制。

删除缓存重试流程:

读取biglog异步删除缓存

重试删除缓存机制还可以吧,就是会形成好多业务代码入侵。其实,还可以这样优化:经过数据库的binlog来异步淘汰key。

以mysql为例吧

您可能还会对下面的文章感兴趣: