分布式系统—最后一致性

(此文来自乐字节)

这篇文章我们聊分布式相关的内容。

提到分布式系统,就一定绕不开“一致性”,这次我们说说:最终一致性。

最终一致性是现在大部分高可用的分布式系统的核心思路。

估计有人对最终一致性不太熟,先来个简单介绍:

最终一致性指的是系统中的所有分散在不同节点的数据,经过一定时间后,最终能够达到符合业务定义的一致的状态。

划重点:

是数据一致性,不是事务一致性(ACID 是事务一致性);

存在条件:多个节点/系统;

不一致可能是暂时的,最终要一致(鬼知道“最终”是多久)

好,正文开始。

莫看江面平如镜,要看水底万丈深

最终一致性,一言以蔽之,过程松,结果紧。不管中间过程如何,结果必须符合业务需求,满足数据一致性的要求。

虽然,在实现中,有各种花样百出的方案,但是本质的思想都是一样的。我们现在就来忽略那些乱花迷眼的过程,仔细探讨下最终一致性的本质。

何事居穷道不穷,乱时还与净时同

在我刚到乐字节不久的时候,能力有限,菜鸟一个,只能做一些小的功能模块。我印象最深的就是订单模块。

用户下单,订单模块收到下单请求后,执行对应的订单业务逻辑。最终,会把订单插入到订单表,并返回下单结果给用户。用户结算后,订单模块就会去根据支付情况去更新订单状态。

就这点事儿,对我这个技术渣渣来说,开始也着实费了一番手脚,不过最终也成了熟手,维护起这个模块来也驾轻就熟了。

这种简单的小日子过了一阵子后,新任务来了!

产品经理告诉我,数据审计部门想要我维护的这个订单模块在订单完成后,能及时分发一份订单数据给他们。他们提供了一个接口,让我直接传数据给他们。

两个问题出现了:

问题 1:用户等待时间变长

最简单的实现就是我更新完订单数据后,再顺序去调用数据审计部门给的接口,把订单数据传过去。

但是,从用户结算成功到更新订单状态这一系列的流程是同步的,假设这一系列流程所花费的时间是 n 毫秒。这就意味着,用户需要等待至少 n 毫秒。

如果再加上传给数据审计部门的操作时间,假设为 m 毫秒,则整个用户就需要等待就 n+m 毫秒。

整个功能用户等待时间成本上升,体验下降。如下图:

问题 2:部分成功,部分失败

引入新的接口后,某些时候调用这个接口可能会失败,比如网络问题啊,验证问题啊,接口服务失败啊,很多原因。那么问题来了,新接口失败的时候怎么处理?

如果订单更新成功,传给数据审计部门的时候失败了,这种情况会让订单模块的后续处理变得很尴尬。

首先你不可能返回给客户端说你这次结算失败了,请求就没失败,你凭什么说人家失败了?

其次,你又不能说这次业务上就是成功的,因为数据审计其实还挺重要的,它是业务逻辑的重要组成部分。

真是进退两难。

我们以前谈到过 CAP,知道如果牺牲一定的一致性就可以保证分区容错性和可用性。

而最终一致性则是不能保证同时让所有的数据当时都符合业务需求,但是我们能保证任何时候服务在内部出现问题的时候都是可对外服务的。

四哥我平时喜欢玩游戏,那我们就用一个淘宝买 Switch 的例子,来解释最终一致性:

如果你想在淘宝同时买一个 Switch 的数字版游戏和一台 Switch,那么你付完钱后,你就可以立刻得到数字版的游戏,但是,对于那台购买的 Switch,你就要等几天,等到快递投递到家才可以拿到。

来梳理下这个例子的细节:

首先淘宝上肯定得有个对顾客售卖 Switch 和数字游戏的商家去接受我们下的订单,并给你一个单号。

你得到了一个数字版游戏,但是没拿到 Switch。

你不知道这个商家背后 Switch 是怎么给你准备的,是不是中间他没货了还得跑别的商家串货,又或者没货等了两天才发给你(延迟发货可以给出别的理由,不再赘述)。这些不重要,重要的是你明确对方接单了他就要完成这笔单子。

你下单成功之后,你就有了保障,你最终会拿到你的 Switch,只是你可能不太肯定什么时候收到。

过了几天,你终于收到货了,恩,恭喜你成功入坑 Switch。

上面的例子就是我们说的最终一致性。但是,这里有个非常非常重要的东西还没有凸显出来,即到底是什么样的原因在驱使我们使用最终一致性?

答案就是数据的分发。

纸上得来终觉浅,绝知此事要躬行

为什么我们会出现需要最终一致性的情况呢?

因为我们需要把数据分发到不同的地方上去,而由于分发数据到不同的地方,就会导致,可能中间分发过程中出现分发成功或者失败的不一致情况,就需要最终一致性这种思路来处理这些情况。

恩,分发数据……OK,你想到了吧?

没错,通过 MQ 分发消息就可以处理分发数据的情况,而这正是最终一致性最常用的实现手段。

我们把要分发的数据打包成消息,再发送给 MQ 中间件。中间件会广播这些数据给所有想要收到这些消息的服务。这些收到消息的服务就根据自己的业务情况对数据进行独立的处理。 回到我们订单模块的那个例子,我们可以采用两种方式使用最终一致性。

先插入数据库,后发消息给数据审计

这个方式,订单模块先更新订单状态。然后,把订单数据打包成消息发送到 MQ 中,订单模块的任务就结束了。剩下的任务就是由数据审计部门根据自己的业务,从 MQ 中获取消息后进行对应的处理。

这个方法里,我们既保证数据库更新成功也保证数据被发送到了 MQ 中。最终,当数据审计部门收到消息并根据消息内容做完对应的处理后,则整体数据达到最终一致的状态。

只插入到 MQ 中

这个方式,订单模块直接收到请求后,将数据打包成消息放入到 MQ 中。

然后,再由订单模块自己和数据审计部门的服务分别从 MQ 中拿到对应的消息,再各自根据自己的业务逻辑该更新数据库的更新数据库,该走自己的审计的走自己的审计,最终达到一致的状态。

小荷才露尖尖角,早有蜻蜓立上头

在以上的例子中,我们描述了最终一致性的核心思路,不保证数据状态能实时满足业务要求,但是就像我们在线购物一样,我们能保证在间隔了一段时间窗口后肯定能满足业务需求。

然而,虽然说起来简单,但是世间上的事情又哪里那么容易呢?根据业务的不同,最终一致性分化出了多种实现思路。比如:

重试 + 逆向模式

在我们做支付时,需要记账,当记账不成功时,我们可能希望能尽可能的重试。当重试达到某种限制后,甚至我们还要通知上游系统去提供一个重试和取消接口,让下游能通知上游重发消息,或者先暂时取消操作。

补救任务模式

在我们做支付记账失败了,我们又尝试了重试 + 逆向模式取消了操作,那么此时就可以创建一个补救任务,等到后期可以保证记账成功的时候去执行这个任务。

异步消息模式

在我们做转账的时候,我们肯定是要保证 A 转出后 B 转入这种业务是强一致性的。然而,可能此时又需要跨服务。同时,我们还想尽量保证性能。

那么,这个时候我们就可以先把本地对数据库的写操作和要跨服务的消息做成事务,然后,后期再根据消息被处理的状态做整体事务的提交和回滚。

可以看到,最终一致性的实现方式是多种多样的,但是,它始终逃不过一个核心,通过消息队列分发数据。在明白了这个根本原则后,以后我们理解各种各样的分布式事务,分布式共识等就会容易许多了。

PS:自学视频阿里P8强烈推荐的8个Java项目实战大合集B站:BV1J64y1R7UN

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

推荐阅读更多精彩内容