分布式学习笔记一

1 常见的分布式事务解决方案

1.1 分布式事务模型

描述分布式事务,常常会使用以下几个名称:

-事务参与者:例如每个数据库就是一个事务参与者

-事务协调者:访问多个数据源的服务程序

-资源管理器(Resource Manager, RM):通常与事务参与者同义

-事务管理器(Transaction Manager, TM): 通常与事务协调者同义

在分布式事务模型中,一个TM管理多个RM,即一个服务程序访问多个数据源;TM是一个全局事务管理器,协调多方本地事务的进度,即使共同提交或回滚,最终达成一种全局的ACID特性。

1.2 二将军问题和幂等性

二将军问题是网络领域的一个经典问题,用于表达计算机网络中互联协议设计的微妙性和复杂性。这里给出一个二将军问题的简化版本:

一支白军被围困在一个山谷中,山谷的左右两侧是蓝军。困在山谷中的白军人数多于山谷两侧的任意一支蓝军,而少于两支蓝军的之和。若一支蓝军对白军单独发起进攻,则必败无疑;但若两军同时发起进攻,则可取胜。两只蓝军的部指挥位于山谷左侧,他希望两支蓝军同时发起进攻,这样就要把命令传到山谷右侧的蓝军,以告知发起进攻的具体时间。假设他们只能派遣士兵穿越白军所在的山谷(唯一的通信信道)来传递消息,那么在穿越山谷时,士兵有可能被俘虏。

网络二将军问题的存在使得消息的发送者往往要重复发送消息,直到收到接收者的确认才认为发送成功,但这往往又会导致消息的重复发送。因此要保证一次事务中的消息无论被发送多少次,接收方有且仅执行一次业务动作,这种保证机制叫做接收方的幂等性。

1.3 两阶段(2PC)提交 & 三阶段(3PC)提交方案

2PC是一种实现分布式事务的简单模型,这两个阶段是:

1)准备阶段:事务协调者向各个事务参与者发起询问请求:“我要执行全局事务了,这个事务涉及到的资源分布在你们这些数据源中,分别是。。。,你们准备好各自的资源(即各自执行本地事务到待提交阶段)”。各个参与者协调者回复yes(表示已准备好,允许提交全局事务)或no(表示参与者无法拿到全局事务所需的本地资源,因为它被其他本地事务锁住了)或超时。

2) 提交阶段:各个参与者回复的都是yes,则协调者向所有参与者发起事务提交操作,然后所有参与者收到后各自执行本地事务提交操作并向协调者发送ACK; 如果任何一个参与者回复no或者超时,则协调者向所有参与者发起事务回滚操作,然后所有参与者收到后各自执行本地事务回滚操作并向协调者发送ACK。

2PC的流程如下图所示

 从上图可以看出,要实现2PC,所有的参与者都要实现三个接口:

  • Prepare(): TM调用该接口询问各个本地事务是否就绪
  • Commit(): TM调用该接口要求各个本地事务提交
  • Rollback(): TM调用该接口要求各个本地事务回滚

可以将这三个接口简单地(但不严谨)理解成XA协议。XA协议是X/Open提出的分布式事务处理标准。MySQL、Oracle、DB2这些主流数据库都实现了XA协议,因此都能被用于实现2PC事务模型。

2PC简明易懂,但存在以下问题:

1) 性能差,在准备阶段,要等待所有的参与者返回,才能进入阶段二,在这期间,各个参与者上面的相关资源被排他地锁住,参与者上面意图使用这些资源的本地事务只能等待。因为存在这种同步阻塞问题,所以影响了各个参与者的本地事务并发度。

2) 准备阶段完成后,如果协调者宕机,所有参与者都收不到提交或回滚指令,导致所有参与者"不知所措";

3) 在提交阶段,协调者向所有参与者发送了提交指令,如果一个参与者未返回ACK,那么协调者不知道这个参与者内部发生了什么(由于网络二将军问题的存在,这个参与者可能根本没收到提交指令;也可能收到了,并成功执行了本地提交,但返回的ACK由于网络故障未送到协调者上),也就无法决定下一步是否进行全体参与者的回滚。

2PC之后又出现了3PC,把两阶段过程变成了三阶段过程,分别是:询问阶段、准备阶段、提交或回滚阶段。3PC利用超时机制解决了3PC的同步阻塞问题,避免资源被永久锁定,进一步加强了整个事务过程的可靠性。但是3PC同样无法应对类似的宕机问题,只不过出现多数据源中数据不一致问题的概率小。

2PC除了性能和可靠性上存在问题,它的适用场景也很局限,它要求参与实现了XA协议,例如使用实现了XA协议的数据库作为参与者可以完成2PC过程。但是在多个系统服务利用api接口相互调用的时候,就不遵守XA协议了,这时候2PC就不适用了。所以2PC在分布式应用场景中很少使用。

1.4 TCC方案

描述TCC方案使用的电脑微服务模型如下图所示,在这个模型中,shopping-service是事务协调者,repo-service和order-service是事务参与者。

TCC就是一种解决多个微服务之间的分布式问题的方案。TCC是Try、Confirm、Cancel三个词的缩写,其本质是一个应用层面上的2PC,同样分为两个阶段:

1)阶段一:准备阶段。协调者调用所有的每个微服务提供的try接口,将整个全局事务涉及到的资源锁定住,若锁定成功try接口向协调者返回yes。

2)阶段二:提交阶段。若所有的服务的try接口在阶段一都返回yes,则进入提交阶段,协调者调用所有服务的confirm接口,各个服务进行事务提交。如果有任何一个服务的try接口在阶段返回no或超时,则协调者调用所有服务的cancel接口。

TCC的流程如下图所示:

这里有个关键问题,既然TCC是一种服务层面上的2PC,它是如何解决2PC无法应对宕机问题的缺陷的呢?答案是不断重试。由于try操作锁住了全局事务涉及的所有资源,保证了业务操作的所有前置条件得到满足,因此无论是confirm阶段失败还是cancel阶段失败都通过不断重试直至confirm或cancel成功(所谓成功就是所有的服务都对confirm或者cancel返回了ACK)。

这里还有个关键问题,在不断重试 confirm 和 cancel 的过程中(考虑到网络二将军问题的存在)有可能重复进行了 confirm 或 cancel,因此还要再保证 confirm 和 cancel 操作具有幂等性,也就是整个全局事务中,每个参与者只进行一次 confirm 或者 cancel。实现 confirm 和 cancel 操作的幂等性,有很多解决方案,例如每个参与者可以维护一个去重表(可以利用数据库表实现也可以使用内存型 KV 组件实现),记录每个全局事务(以全局事务标记 XID 区分)是否进行过 confirm 或 cancel 操作,若已经进行过,则不再重复执行。

TCC 由支付宝团队提出,被广泛应用于金融系统中。我们用银行账户余额购买基金时,会注意到银行账户中用于购买基金的那部分余额首先会被冻结,由此我们可以猜想,这个过程大概就是 TCC 的第一阶段。

1.5 事务状态表方案

另外有一种类似TCC的事务解决方案,借助事务状态表来实现。

1.6 基于消息中间件的最终一致性事务方案

无论是2PC & 3PC还是TCC、事务状态表,基本都遵守XA协议的思想,即这些方案本质上都是事务协调者协调各个事务参与者的本地事务的进度,使所有本地事务共同提交或回滚,最终达成一种全局的ACID特性。在协调的过程中,协调者需要收集各个本地事务的当前状态,并根据这些状态发出下一阶段的操作指令。

但是这些全局事务方案由于操作频繁、时间跨度大,或者在全局事务期间会排他的锁住相关资源,使得整个分布式系统的全局事务的并发度不会太高。这很难满足电商等高并发场景对事务吞吐量的要求,因此互联网服务提供商探索出了很多与XA协议背道而驰的分布式事务解决方案。其中利用消息中间件实现的最终一致性全局事务就是一个经典方案。

一是生产者重复生产,二是中间件重传。为了实现业务的幂等性, repo-service中维护了一张判重表,这张表中记录了被成功处理的消息id。repo-service每次接收到新的消息都先判断消息是否成功处理过,若是的话不再重复处理。

基于消息中间间的最终一致性全局事务方案是互联网公司在高并发场景中探索出的一种创新型应用模式,利用MQ实现微服务之间的异步调用、解耦合和流量削峰,支持全局事务的高并发,并保证分布式数据记录的最终一致性。

2 Seata in AT mode的实现

Seata为用户提供了AT、TCC、SAGA和XA事务模式。其中AT模式是Seata主推的事务模式,因此本章分析Seata in AT mode的实现。使用AT有一个前提,那就是微服务使用的数据库必须是支持事务的关系型数据库。

学习资料:1.4 w字,25 张图让你彻底掌握分布式事务原理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值