分布式事务入门 —— 概述

1、本地事务

  关于本地事务相关概念请参考《数据库事务Transaction》《MySQL实现架构、事务概述、锁机制》。在这两篇文章中,主要讲解了本地事务的基本概念、ACID特性和隔离级别等内容。

2、分布式事务

  在传统的单节点应用中,本地事务就可以满足需求了。但随着互联网时代的到来,数据量的急剧增加、服务复杂程度越来越高,为了解决这些问题,分库分表、微服务架构等技术或思想就应用而生了,这个时候,多个服务资源或多个数据库资源就需要在同一个事务中进行管理了,但是本地事务却对此无能为力,所以分布式事务就出现了。

2.1、应用场景

1、跨库事务

  跨库事务指的是,一个应用某个功能需要操作多个库,不同的库中存储不同的业务数据。下图演示了一个服务同时操作2个库的情况:
在这里插入图片描述
2、分库分表

   通常一个库数据量比较大或者预期未来的数据量比较大,都会进行水平拆分,也就是分库分表。如下图,将数据库B拆分成了2个库:
在这里插入图片描述
3、服务化(SOA)

   微服务架构是目前一个比较一个比较火的概念。对比比较复杂的应用系统,一般会拆分成不同的独立服务,以简化业务逻辑。拆分后,独立服务之间通过RPC框架来进行远程调用,实现彼此的通信。下图演示了一个3个服务之间彼此调用的架构:
在这里插入图片描述

上述内容来自《分布式事务概述》

2.2、CAP原理

在这里插入图片描述

  • C - Consistent ,一致性。具体是指,操作成功以后,所有的节点,在同一时间,看到的数据都是完全一致的。所以,一致性,说的就是数据一致性。
  • A - Availability ,可用性。指服务一致可用,在规定的时间内完成响应。
  • P - Partition tolerance ,分区容错性。指分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供服务。

  CAP原理指出,这3个指标不能同时满足,最多只能满足其中的两个。

  我们之所以使用分布式系统,就是为了在某个节点不可用的情况下,整个服务对外还是可用的,这正是满足P(分区容错性)。如果我们的服务不满足P(分区容错性),那么我们的系统也就不是分布式系统了,所以,在分布式系统中,P(分布容错性)总是成立的。

  A和B是两个数据节点,A向B同步数据,并且作为一个整体对外提供服务。由于我们的系统保证了P(分区容错性),那么A和B的同步,我们允许出现故障。接下来我们再保证A(可用性),也就是说A和B同步出现问题时,客户端还能够访问我们的系统,那么客户端既可能访问A也可能访问B,这时,A和B的数据是不一致的,所以C(一致性)不能满足。

  如果我们满足C(一致性),也就是说客户端无论访问A还是访问B,得到的结果都是一样的,那么现在A和B的数据不一致,需要等到A和B的数据一致以后,也就是同步恢复以后,才可对外提供服务。这样我们虽然满足了C(一致性),却不能满足A(可用性)。

  所以,我们的系统在满足P(分区容错性)的同时,只能在A(可用性)和C(一致性)当中选择一个不能CAP同时满足。我们的分布式系统只能是AP或者CP。

2.3、X/Open DTP模型(Distributed Transaction Processing)

1、模型元素
  在《Distributed Transaction Processing: Reference Model》第3版中,规定了构成DTP模型的5个基本元素:

  • 应用程序(Application Program ,简称AP):用于定义事务边界(即定义事务的开始和结束),并且在事务边界内对资源进行操作。
  • 资源管理器(Resource Manager,简称RM):如数据库、文件系统等,并提供访问资源的方式。
  • 事务管理器(Transaction Manager ,简称TM):负责分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚等。
  • 通信资源管理器(Communication Resource Manager,简称CRM):控制一个TM域(TM domain)内或者跨TM域的分布式应用之间的通信。
  • 通信协议(Communication Protocol,简称CP):提供CRM提供的分布式应用节点之间的底层通信服务。

  其中由于通信资源管理器(Communication Resource Manager)和通信协议(Communication Protocol)是一对好基友,从Communication Protocol的简称CP上就可以看出来,两个元素的关系不一般,因此有的文章在介绍DTP模型元素时,只提到了通信资源管理器…

2、模型实例(Instance of the Model)

在这里插入图片描述
  一个DTP模型实例,至少有3个组成部分:AP、RMs、TM。如上图所示,一般用于跨库事务处理,即当个应用操作多个库,在这里就是一个AP需要操作多个RM上的资源。AP通过TM来声明一个全局事务,然后操作不同的RM上的资源,最后通知TM来提交或者回滚全局事务。

  如果分布式事务中需要跨多个服务,类似于前面提到的SOA场景,这个时候就需要引入通信资源管理器CRM,如下所示:
在这里插入图片描述

2.4、XA规范

  XA规范的最主要的作用是,就是定义了RM-TM的交互接口。
在这里插入图片描述
XA Interface

XA规范中定义的RM 和 TM交互的接口如下图所示:
在这里插入图片描述

2.5、BASE原理

  BASE是Basically Available(基本可用), Soft-state(软状态), Eventually consistent(最终一致)的缩写。

  • Basically Available,基本可用是指分布式系统在出现故障的时候,允许损失部分可用性,即保证核心可用。电商大促时,为了应对访问量激增,部分用户可能会被引导到降级页面,服务层也可能只提供降级服务。这就是损失部分可用性的体现。
  • 软状态( Soft State)
    软状态是指允许系统存在中间状态,而该中间状态不会影响系统整体可用性。分布式存储中一般一份数据至少会有两到三个副本,允许不同节点间副本同步的延时就是软状态的体现。mysql replication的异步复制也是一种体现。
  • 最终一致性( Eventual Consistency)
    最终一致性是指系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。弱一致性和强一致性相反,最终一致性是弱一致性的一种特殊情况。

  BASE模型是传统ACID模型的反面,不同与ACID,BASE强调牺牲高一致性,从而获得可用性,数据允许在一段时间内的不一致,只要保证最终一致就可以了。

  在分布式事务的解决方案中,它们都是依赖了ACID或者BASE的模型而实现的。像基于XA协议的两阶段提交和实物补偿机制就是基于ACID实现的。而基于本地消息表和基于MQ的最终一致方案都是通过BASE原理实现的。

2.6、两阶段提交协议(2PC,Two Phase Commit)

  基于XA协议的两阶段提交,由一个事务管理器(TM)和多个资源管理器(RM)组成,然后提交分为两个阶段:prepare和commit。

在这里插入图片描述
  在第一个阶段,事务管理器(TM)通知资源管理器(RM)提交它们的事务分支,如果RM判断可以提交,就返回肯定答复,否则,就返回否定答复。发送否定答复前,需要回滚当前分支的事务。对于mysql数据库来说,在第一阶段,事务管理器向所有涉及到的数据库服务器发出prepare"准备提交"请求,数据库收到请求后执行数据修改和日志记录等处理,处理完成后只是把事务的状态改成"可以提交",然后把结果返回给事务管理器。
在这里插入图片描述
  在第二个阶段,事务管理器(TM)根据第一阶段各个资源管理器(RM)返回的结果,决定是提交事务,还是回滚事务。如果所有的RM都prepare成功,那么TM通知所有的RM进行提交;如果有RM prepare失败的话,则TM通知所有RM回滚自己的事务分支。对于mysql数据库来说,如果第一阶段中所有数据库都prepare成功,那么事务管理器向数据库服务器发出"确认提交"请求,数据库服务器把事务的"可以提交"状态改为"提交完成"状态,然后返回应答。如果在第一阶段内有任何一个数据库的操作发生了错误,或者事务管理器收不到某个数据库的回应,则认为事务失败,回撤所有数据库的事务。数据库服务器收不到第二阶段的确认提交请求,也会把"可以提交"的事务回撤。

XA规范对两阶段提交协议有2点优化:

  1. 只读断言
    在Phase 1中,RM可以断言“我这边不涉及数据增删改”来答复TM的prepare请求,从而让这个RM脱离当前的全局事务,从而免去了Phase 2。这种优化发生在其他RM都完成prepare之前的话,使用了只读断言的RM早于AP其他动作(比如说这个RM返回那些只读数据给AP)前,就释放了相关数据的上下文(比如读锁之类的),这时候其他全局事务或者本地事务就有机会去改变这些数据,结果就是无法保障整个系统的可序列化特性——通俗点说那就会有脏读的风险。
  2. 一阶段提交
    如果需要增删改的数据都在同一个RM上,TM可以使用一阶段提交——跳过两阶段提交中的Phase 1,直接执行Phase 2。这种优化的本质是跳过Phase 1,RM自行决定了事务分支的结果,并且在答复TM前就清除掉事务分支信息。对于这种优化的情况,TM实际上也没有必要去可靠的记录全局事务的信息,在一些异常的场景下,此时TM可能不知道事务分支的执行结果。

两阶段提交协议(2PC)存在的问题

  1. 同步阻塞
    两阶段提交执行过程中,所有的参与者都需要听从协调者的统一调度,期间处于阻塞状态而不能从事其他操作,这样效率极其低下。
  2. 存在数据不一致
    在第二阶段提交时,如果出现异常(超时或失败),这个时候可能会导致一部分资源管理接收到了commit请求,提交了事务,一部分资源管理器没有接收到commit请求,导致回滚,最后出现了数据不一致性。
  3. 事务管理器的单点故障
    由于事务管理器的重要性,一旦协调者TM发生故障。参与者RM会一直阻塞下去。
2.7、三阶段提交协议(3PC,Three-phase commit)

  三阶段提交(3PC),是二阶段提交(2PC)的改进版本。与两阶段提交相比,主要有以下两点不同:

  1. 引入超时机制。同时在协调者和参与者中都引入超时机制。

  2. 在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。

在这里插入图片描述
  三阶段提交有CanCommit、PreCommit、DoCommit三个阶段,如上所示。

CanCommit阶段

  3PC的CanCommit阶段其实和2PC的准备阶段很像。事务管理器(协调者)向资源管理器(参与者)发送commit请求,参与者如果可以提交就返回Yes响应,否则返回No响应。

1.事务询问 协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。

2.响应反馈 参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No。

PreCommit阶段

  协调者根据参与者的反应情况来决定是否可以继续事务的PreCommit操作。根据响应情况,有以下两种可能:

第一种情况:假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务的预执行。

  1. 发送预提交请求 协调者向参与者发送PreCommit请求,并进入Prepared阶段。

  2. 事务预提交 参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。

  3. 响应反馈 如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。

第二种情况:假如有任何一个参与者向协调者发送了No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。

  1. 发送中断请求 协调者向所有参与者发送abort请求。

  2. 中断事务 参与者收到来自协调者的abort请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。

doCommit阶段

   该阶段进行真正的事务提交,也可以分为以下两种情况:

第一种情况:执行提交

  1. 发送提交请求 协调接收到参与者发送的ACK响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。

  2. 事务提交 参与者接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。

  3. 响应反馈 事务提交完之后,向协调者发送Ack响应。

  4. 完成事务 协调者接收到所有参与者的ack响应之后,完成事务。

第二种情况:中断事务 协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。

  1. 发送中断请求 协调者向所有参与者发送abort请求

  2. 事务回滚 参与者接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。

  3. 反馈结果 参与者完成事务回滚之后,向协调者发送ACK消息

  4. 中断事务 协调者接收到参与者反馈的ACK消息之后,执行事务的中断。

2.8、2PC与3PC的区别

  相对于2PC,3PC主要解决的单点故障问题,并减少阻塞,因为一旦参与者无法及时收到来自协调者的信息之后,他会默认执行commit。而不会一直持有事务资源并处于阻塞状态。但是这种机制也会导致数据一致性问题,因为,由于网络原因,协调者发送的abort响应没有及时被参与者接收到,那么参与者在等待超时之后执行了commit操作。这样就和其他接到abort命令并执行回滚的参与者之间存在数据不一致的情况。

2.9、TCC 分布式事务

在这里插入图片描述
如上图所示:

  • 一个完整的业务活动由一个主业务服务与若干从业务服务组成。

  • 主业务服务负责发起并完成整个业务活动。

  • 从业务服务提供TCC型业务操作。

  • 业务活动管理器控制业务活动的一致性,它登记业务活动中的操作,并在业务活动提交时进行confirm操作,在业务活动取消时进行cancel操作

TCC和2PC/3PC很像,不过TCC的事务控制都是业务代码层面的,而2PC/3PC则是资源层面的。

各阶段规范

  TCC事务其实主要包含两个阶段:Try阶段、Confirm/Cancel阶段。

  从TCC的逻辑模型上我们可以看到,TCC的核心思想是,try阶段检查并预留资源,确保在confirm阶段有资源可用,这样可以最大程度的确保confirm阶段能够执行成功。

  1. try-尝试执行业务
    完成所有业务检查(一致性)
    预留必须业务资源(准隔离性)

  2. confirm-确认执行业务
    真正执行业务
    不作任何业务检查
    只使用Try阶段预留的业务资源
    Confirm操作必须保证幂等性

  3. cancel-取消执行业务
    释放Try阶段预留的业务资源
    Cancel操作必须保证幂等性

3、参考文档:

1、《终于有人把“TCC分布式事务”实现原理讲明白了!》
2、《分布式事务概述》
3、 《pageShardingSphere官方文档-分布式事务》

猜你喜欢

转载自blog.csdn.net/hou_ge/article/details/113347787