分布式系统学习10:分布式事务

这是小卷对分布式系统架构学习的第13篇文章,今天学习面试中高频问题:分布式事务,为什么要用分布式事务,分布式事务的实现方案有哪些,方案对比优缺点;

1.知识体系

分布式事务1.png

1.为什么要用分布式事务

单体架构时,以本地事务为例,业务场景是下单场景,用户下单、创建订单、扣减库存这些操作都可以在一个数据库事务中完成。

分布式事务2.png

而随着业务的增长,系统转变为分布式系统,原有的单体架构也拆分为多个微服务。下单场景需要在多个服务间操作,需要保证所有操作都能成功,保证整个下单流程的数据一致性,就需要用到分布式事务了

分布式事务3.png

2.理论

  • 分布式理论的CP -> 刚性事务

遵循ACID,对数据要求强一致性

  • 分布式理论的AP+BASE -> 柔性事务

遵循BASE,允许一定时间内不同节点的数据不一致,但要求最终一致。

这里重新复习一遍BASE理论是什么:

  • 基本可用 Basically Available
  • 软状态 Soft State
  • 最终一致性 Eventually Consistent

基本可用:是指系统出现未知故障时,还是能用的;

软状态:允许系统存在中间态,即所有副本数据允许存在延迟;

最终一致性:存在软状态,在一定时间后,所有副本数据保持一致,从而达到数据最终一致性;

3.刚性事务(CP模式)

刚性事务指的是强一致性,基础是XA协议,XA协议是一个基于数据库的分布式事务协议,其分为两部分:事务管理器(Transaction Manager)*和*本地资源管理器(Resource Manager)**。事务管理器作为一个全局的调度者,负责对各个本地资源管理器统一号令提交或者回滚;

而2PC (两阶段提交)和3PC(三阶段提交)都是由XA协议衍生出来的

3.1两阶段提交(2PC)

引入一个作为协调者(coordinator)的组件来统一掌控所有参与者(participant)的操作结果,并最终指示这些节点是否要把操作结果进行真正的提交

2PC指的是 Prepare & Commit

第一阶段:准备阶段

  • 协调者向所有参与者发送REQUEST-TO-PREPARE
  • 当参与者收到REQUEST-TO-PREPARE消息后,它向协调者发送消息PREPARE或者NO,表示事务是否准备好;如果发送是NO,那么事务回滚;

第二阶段:提交阶段

  • 协调者收集所有参与者的返回信息,如果所有参与者都回复PREPARED,那么协调者向所有参与者发送COMMIT消息,否则,协调者发送ABORT消息
  • 参与者收到协调者发来的Commit消息或Abort消息,它将执行提交或回滚,并向协调者发送DONE消息确认
分布式事务4.png

两阶段提交的缺点:

  • 网络抖动导致数据不一致:第二阶段协调者向参与者发送commit命令后,如果发生网络抖动,有一部分参与者未收到commit请求,则无法执行事务提交,影响整个系统数据一致性;
  • 超时导致的同步阻塞问题:2PC中所有参与者节点都是事务阻塞型,当一个节点通信超时,其余参与者都会被阻塞;
  • 单点故障的风险:整个过程严重依赖协调者,如果协调者故障,参与者处于锁定资源的状态,无法完成事务commit的操作。即使重新选择一个协调者,也无法解决因前一个协调者宕机导致的阻塞问题;

2PC只适用于两个数据库(数据库实现了XA协议)之间使用,限制较大,两个系统间无法使用

3.2 三阶段提交(3PC)

在2PC的基础上,第一阶段和第二阶段中插入一个准备阶段,同时在协调者和参与者中都引入超时机制,当参与者为收到协调者发送的commit请求后,也会对本地事务commit,不会一直阻塞等待

过程如下:

  • CanCommit:协调者向所有参与者发生Cancommit命令,算法可以执行事务提交操作,如果都响应YES,则下一阶段;
  • PreCommit:协调者向所有参与者发送Precommit命令,是否可以进行事务预提交操作。参与者如果已执行了事务操作,则回复YES,进入下一阶段。如果回复NO,或者协调者没有收到参与者的回复,协调者就向所有参与者发送Abort请求,执行事务的中断;
  • DoCommit:所有参与者已经回复YES,协调者发DoCommit命令正式提交事务,如果协调者没有收到参与者的ACK响应,则发Abort请求给所有参与者,中断事务。
分布式事务5.png

小结:

2PC存在使用限制的问题,3PC存在数据不一致的问题,两者在实际中很少使用;

4.柔性事务(AP +BASE 最终一致性)

柔性事务要求最终一致性,允许有中间态,柔性事务可以分为:TCC、Saga、本地消息表、MQ事务方案、最大努力通知

4.1 TCC 补偿事务

TCC(Try Confirm Cancel)补偿事务,与2PC不同的是,2PC是在DB层面,TCC是在应用层面

三个操作步骤:

  • Try阶段:完成业务检查,预留必须得业务资源;
  • Confirm阶段:执行业务逻辑,只使用Try阶段预留的业务资源。Confirm需满足幂等性,保证一个分布式事务只成功一次;
  • Cancel阶段:取消操作,释放Try阶段预留的业务资源,需要幂等性;
分布式事务6.png

4.2 Saga事务

Saga可以看做一个异步的、利用队列实现的补偿事务。

由一系列本地事务构成,每个本地事务更新了数据库后,会发布一条消息来触发Saga中的下一个本地事务的执行,如果某个本地事务失败了,Saga会执行这个失败事务之前 已提交的所有事务的补偿操作

Saga的实现最流行的两种方式是:

  • 基于事件的方式。这种方式没有协调中心,整个模式的工作方式就像舞蹈一样,各个舞蹈演员按照预先编排的动作和走位各自表演,最终形成一只舞蹈。处于当前Saga下的各个服务,会产生某类事件,或者监听其它服务产生的事件并决定是否需要针对监听到的事件做出响应
  • 基于命令的方式。这种方式的工作形式就像一只乐队,由一个指挥家(协调中心)来协调大家的工作。协调中心来告诉Saga的参与方应该执行哪一个本地事务

基于事件的方式

事务回滚:

  • 基于事件的回滚,需要相关服务提供补偿操作接口,某个节点发生无法执行事件操作时,需要发送事件通知,其他已执行了事务的节点监听事件并回应
  • 优点:简单容易理解,适用于分布式事务只有2-4个步骤的场景。示例如:下单-扣款-库存减货-物流服务-订单完成 这样简单的场景
  • 缺点:参与业务方多时,会出现很多问题

4.3本地消息表

本地消息表的核心是将分布式事务拆成本地事务进行处理,最初是由eBay提出的

下面以一个订单场景具体说明本地消息表的实现

例如,可以在订单库新增一个消息表,将新增订单和新增消息放到一个事务里完成,然后通过轮询的方式去查询消息表,将消息推送到 MQ,库存服务去消费 MQ。

分布式事务7.png

执行流程为:

  1. 订单服务,在一个事务里增加一个订单和一条消息,并提交
  2. 订单服务通过轮询的方式,查出未同步的消息,发到MQ,从设置失败重试机制;
  3. 库存服务,负责接收MQ消息,进行消费修改库存,由消费方保证幂等性;
  4. 库存服务修改成功后,调RPC接口修改订单服务的消息表状态;
  5. 修改失败,等待重试

优点:方案轻量,消息可靠性不依赖消息中间件;

缺点:与业务强耦合,不可公用,消息数据与业务库同库,占资源;

4.4 MQ消息事务

MQ事务是对本地消息表的封装,将本地消息表存到MQ内部了,而不是业务数据库

将两个事务通过消息队列进行异步解耦,加上重试机制保证最终一致性

分布式事务8.png

发消息逻辑如下:

分布式事务9.png
  • 发送方向MQ server端发送half消息;
  • MQ server将消息持久化后,发ACK给发送方
  • 发送方开始执行本地事务
  • 执行完成后,向MQ server提交二次确认
  • MQ server收到commit状态将半消息标记为可投递,订阅方将收到消息;MQ server如收到rollback状态则删除半消息,订阅方收不到消息;

缺点:一次消息发送需要两次网络请求(half + commit/rolllback消息)

4.5 最大努力通知

也成为定期校对,是对MQ事务的进一步优化。

事务发起方增加了消息校对接口,也就是查询接口,事务接收方可以自行调用接口主动获取操作结果

逻辑如下:

事务主动方尽最大努力(重试,轮询....)将事务发送给事务接收方,但是仍然存在消息接收不到,此时需要事务被动方主动调用事务主动方的消息校对接口查询业务消息并消费,这种通知的可靠性是由事务被动方保证的

分布式事务10.png

适用场景:

业务通知类型的场景,如微信交易的结果,就是通过最大努力通知方式通知各个商户,既有回调通知,也有交易查询接口

5. Seata框架

开源的分布式事务解决方案,提供了AT、TCC、SAGA、XA事务模式,不需要自己手动实现分布式事务,直接使用框架就行

有以下几个角色:

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

推荐阅读更多精彩内容