入门分布式事务,事务协调方法之 2PC & 3PC & XA

分布式事务

什么是分布式一致性

在分布式系统中,为了保证数据的高可用,通常,我们会将数据保留多个副本(replica),这些副本会放置在不同的物理的机器上。为了对用户提供正确的增\删\改\查等语义,我们需要保证这些放置在不同物理机器上的副本是一致的。

为了解决这种分布式一致性问题,前人在性能和数据一致性的反反复复权衡过程中总结了许多典型的协议和算法。其中比较著名的有二阶提交协议(Two Phase Commitment Protocol)、三阶提交协议(Three Phase Commitment Protocol)和Paxos算法

解决分布式事务的主要可以归结为协调事务与最终一致性方案,像我们今天要说的主要是 2PC & 3PC 是属于协调事务其中的一部分。最终一致性方案我们之后再提。

什么是事务

事务处理几乎在每一个信息系统中都会涉及,它存在的意义是为了保证系统中所有的数据都是符合期望的,且相互关联的数据之间不会产生矛盾,即数据状态的一致性Consistency)。

按照数据库的经典理论,要达成这个目标,需要三方面共同努力来保障。

  • 原子性Atomic):在同一项业务处理过程中,事务保证了对多个数据的修改,要么同时成功,要么同时被撤销。
  • 隔离性Isolation):在不同的业务处理过程中,事务保证了各自业务正在读、写的数据互相独立,不会彼此影响。
  • 持久性Durability):事务应当保证所有成功被提交的数据修改都能够正确地被持久化,不丢失数据。

以上四种属性即事务的“ACID”特性,但笔者对这种说法其实不是太认同,因为这四种特性并不正交,A、I、D 是手段,C 是目的,前者是因,后者是果,弄到一块去完全是为了拼凑个单词缩写。

事务的概念虽然最初起源于数据库系统,但今天已经有所延伸,而不再局限于数据库本身了,所有需要保证数据一致性的应用场景,包括但不限于数据库、事务内存、缓存、消息队列、分布式存储,等等,都有可能会用到事务,后文里笔者会使用“数据源”来泛指所有这些场景中提供与存储数据的逻辑设备,但是上述场景所说的事务和一致性含义可能并不完全一致,说明如下。

  • 当一个服务只使用一个数据源时,通过 A、I、D 来获得一致性是最经典的做法,也是相对容易的。此时,多个并发事务所读写的数据能够被数据源感知是否存在冲突,并发事务的读写在时间线上的最终顺序是由数据源来确定的,这种事务间一致性被称为“内部一致性”。
  • 当一个服务使用到多个不同的数据源,甚至多个不同服务同时涉及多个不同的数据源时,问题就变得相对困难了许多。此时,并发执行甚至是先后执行的多个事务,在时间线上的顺序并不由任何一个数据源来决定,这种涉及多个数据源的事务间一致性被称为“外部一致性”。

外部一致性问题通常很难再使用 A、I、D 来解决,因为这样需要付出很大乃至不切实际的代价;但是外部一致性又是分布式系统中必然会遇到且必须要解决的问题,为此我们要转变观念,将一致性从“是或否”的二元属性转变为可以按不同强度分开讨论的多元属性,在确保代价可承受的前提下获得强度尽可能高的一致性保障,也正因如此,事务处理才从一个具体操作上的“编程问题”上升成一个需要全局权衡的“架构问题”。

人们在探索这些解决方案的过程中,产生了许多新的思路和概念,有一些概念看上去并不那么直观,在本章里,笔者会通过同一个场景事例讲解如何在不同的事务方案中处理来贯穿、理顺这些概念。

事务划分

其实事务根据不同的场景会划分成很多类型,比如 本地事务、全局事务、共享事务、分布式事务,我们今天来讲的主要是分布式事务相关内容的全局事务以及 2PC 与 3PC。

对于其他事务我们就不仔细提了。

谈谈一致性

一致性就是数据保持一致,在分布式系统中,可以理解为多个节点中数据的值是一致的。

  • 强一致性:这种一致性级别是最符合用户直觉的,它要求系统写入什么,读出来的也会是什么,用户体验好,但实现起来往往对系统的性能影响大
  • 弱一致性:这种一致性级别约束了系统在写入成功后,不承诺立即可以读到写入的值,也不承诺多久之后数据能够达到一致,但会尽可能地保证到某个时间级别(比如秒级别)后,数据能够达到一致状态
  • 最终一致性:最终一致性是弱一致性的一个特例,系统会保证在一定时间内,能够达到一个数据一致的状态。这里之所以将最终一致性单独提出来,是因为它是弱一致性中非常推崇的一种一致性模型,也是业界在大型分布式系统的数据一致性上比较推崇的模型

分布式事务

分布式事务

是指会涉及到操作多个数据库的事务。

其实就是将对同一库事务的概念扩大到了对多个库的事务。目的是为了保证分布式系统中的数据一致性。分布式事务处理的关键是必须有一种方法可以知道事务在任何地方所做的所有动作,提交或回滚事务的决定必须产生统一的结果(全部提交或全部回滚)

在分布式系统中,各个节点之间在物理上相互独立,通过网络进行沟通和协调。

由于存在事务机制,可以保证每个独立节点上的数据操作可以满足ACID。但是,相互独立的节点之间无法准确的知道其他节点中的事务执行情况。所以从理论上讲,两台机器理论上无法达到一致的状态。

如果想让分布式部署的多台机器中的数据保持一致性,那么就要保证在所有节点的数据写操作,要么全部都执行,要么全部的都不执行。但是,一台机器在执行本地事务的时候无法知道其他机器中的本地事务的执行结果。所以他也就不知道本次事务到底应该commit还是

roolback。所以,常规的解决办法就是引入一个“协调者”的组件来统一调度所有分布式节点的执行。

如何实现分布式一致性呢?

二阶提交协议三阶提交协议就是最早提出解决分布式一致性的方案。

2PC - 二阶段提交协议

二阶段提交(Two-phaseCommit)是指,在计算机网络以及数据库领域内,为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性当一个事务跨越多个节点时,为了保持事务的ACID特性,引入一个作为协调者的组件

二阶段提交的算法思路可以概括为:

  • 参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。

所谓的两个阶段是指:

  • 第一阶段:voting phase 投票阶段
  • 第二阶段:commit phase 提交阶段
    在这里插入图片描述
投票阶段

事务协调者给每个参与者发送Prepare消息,每个参与者要么直接返回失败(如权限验证失败),要么在本地执行事务,写本地的redo和undo日志,但不提交,到达一种“万事俱备,只欠东风”的状态。

投票阶段的三步骤:

在这里插入图片描述

1)协调者节点向所有参与者节点询问是否可以执行提交操作(vote),并开始等待各参与者节点的响应。

2)参与者节点检查事务权限,执行询问发起为止的所有事务操作,并将Undo信息和Redo信息写入日志。

【注:为什么在执行任务前需要先写本地日志,主要是为了故障后恢复用,本地日志起到现实生活中凭证 的效果,如果没有本地日志(凭证),出问题容易死无对证;】

3)各参与者节点响应协调者节点发起的询问。如果参与者节点的事务操作实际执行成功,则它返回一个”同意”消息;如果参与者节点的事务操作实际执行失败,则它返回一个”中止”消息。

提交阶段

如果协调者收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据协调者的指令执行提交或者回滚操作,释放所有事务处理过程中使用的锁资源。(注意:必须在最后阶段释放锁资源)

接下来分两种情况分别讨论提交阶段的过程。

情况 1

当协调者节点从所有参与者节点获得的响应消息都为”同意”时,提交过程如下图所示:

在这里插入图片描述
协调者节点向所有参与者节点发出”正式提交(commit)”的请求。
2)参与者节点正式完成操作,并释放在整个事务期间内占用的资源。
3)参与者节点向协调者节点发送”完成”消息。
4)协调者节点受到所有参与者节点反馈的”完成”消息后,完成事务。

情况 2
如果任一参与者节点在第一阶段返回的响应消息为”中止”,或者 协调者节点在第一阶段的询问超时之前无法获取所有参与者节点的响应消息时:
在这里插入图片描述

1)协调者节点向所有参与者节点发出”回滚操作(rollback)”的请求。
2)参与者节点利用之前写入的Undo信息执行回滚,并释放在整个事务期间内占用的资源。
3)参与者节点向协调者节点发送”回滚完成”消息。
4)协调者节点受到所有参与者节点反馈的”回滚完成”消息后,取消事务。

不管最后结果如何,第二阶段都会结束当前事务。

  • 二阶段提交的缺点

二阶段提交看起来确实能够提供原子性的操作,但是不幸的事,二阶段提交还是有几个缺点的:
在这里插入图片描述

1、同步阻塞问题
执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。也就是说从投票阶段到提交阶段完成这段时间,资源是被锁住的。

2、单点故障
由于协调者的重要性,
一旦协调者发生故障。参与者会一直阻塞下去。
尤其在第二阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。
【协调者发出Commmit消息之前宕机的情况】
(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题

3、数据不一致

在二阶段提交的阶段二中,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据不一致性的现象。

4、二阶段无法解决的问题:------ 极限情况下,对某一事务的不确定性!【协调者发出Commmit消息之后宕机的情况】
协调者再发出commit消息之后宕机,而唯一接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者,这条事务的状态也是不确定的,没人知道事务是否被已经提交。

由于二阶段提交存在着诸如同步阻塞、单点问题、脑裂等缺陷,所以,研究者们在二阶段提交的基础上做了改进,提出了三阶段提交。

扩展
TiDB 的两阶段提交

相同点

  • 两个阶段:TiDB的两阶段提交同样遵循基本的2PC框架,包括“准备阶段”和“提交/回滚阶段”。
  • 确保数据一致性:两者都是为了保证事务在分布式系统中的一致性,确保要么所有节点都提交事务,要么都不提交。

不同点

  • 设计背景:传统的两阶段提交是为了通用的分布式事务设计,而TiDB的两阶段提交是专门为TiDB这种分布式数据库系统量身定制的。
  • 实现细节:TiDB在实现两阶段提交时做了很多针对性的优化。例如,它可能在事务冲突检测、锁定资源等方面有独特的处理方式,以适应其分布式架构。
  • 性能优化:TiDB的两阶段提交可能包含更多的性能优化措施,以减少跨网络通信的开销和提高事务处理的效率。这些优化可能包括数据局部性考虑、事务日志处理方式等。
  • 故障处理:在故障恢复和事务持久性方面,TiDB可能有自己的机制,例如利用其自身的存储引擎特性来优化数据恢复过程。
  • 可扩展性和灵活性:作为一个为大规模分布式环境设计的系统,TiDB的两阶段提交可能更注重于扩展性和灵活性,以适应大量节点和高并发的场景。

结论

虽然TiDB的两阶段提交在高层框架上与传统的两阶段提交相似,但它通过特定的优化和调整更适合于其分布式数据库的环境。这些差异体现了TiDB在保持一致性和提高性能方面的特定考量。在选择分布式数据库和事务协议时,重要的是要考虑系统的具体需求和运行环境。

平常所说的两阶段提交

相同点

  • 基本框架:无论在哪种场景下讨论,两阶段提交的基本框架是相同的。
  • 它都包含两个阶段:准备阶段和提交/回滚阶段。
  • 一致性保证:两者都旨在确保分布式系统中事务的一致性。即要么所有节点都提交事务,要么都不提交。

可能的不同点

  • 实现细节:不同系统中的两阶段提交可能在实现细节上有所差异。这些差异可能源于系统架构、性能要求、容错机制等方面的考量。
  • 性能优化:在不同的系统中,可能会采取不同的优化措施来提高两阶段提交的效率,减少其对系统性能的影响。
  • 故障处理和恢复:不同的系统可能会采用不同的策略来处理和恢复事务协议中的失败情况,这取决于系统的容错需求和可用资源。
  • 应用场景:某些系统可能会根据其特定的应用场景对两阶段提交进行调>整,以更好地满足其需求。

结论

当我们在不同上下文中讨论两阶段提交时,基本的协议框架和目标是一致的,但实现的具体细节、性能优化、故障处理等方面可能会根据具体的系统和应用场景有所不同。无论在哪种情况下,两阶段提交的主要目的都是确保在分布式系统中处理事务时的数据一致性。

TiDB 在两阶段提交中的参与者是谁?协调者是谁?

参与者

参与者为 TiKV,在 TiDB 的两阶段提交过程中,参与者通常是指存储数据的节点。TiDB采用了 TiKV 作为其存储层,所以参与者在这里指的是TiKV 的节点。每个 TiKV 节点负责存储数据的一部分,并在两阶段提交过程中执行相关的操作,如锁定资源、写入数据、回滚或提交事务等。

协调者

协调者在 TiDB 的两阶段提交中通常是指负责协调事务的组件,这通常是 TiDB 服务器本身。TiDB 服务器接收来自客户端的事务请求,然后它负责在两阶段提交过程中与多个 TiKV 节点通信,协调整个事务的提交或回滚。

两阶段提交过程概述

  • 第一阶段(预提交):TiDB服务器(作为协调者)向TiKV节点(参与者)发送预提交请求。TiKV节点在收到请求后执行事务操作,并将结果返回给TiDB服务器。
  • 第二阶段(提交或回滚):根据第一阶段的结果,TiDB服务器会决定是提交事务还是回滚事务。如果所有TiKV节点都成功预提交,TiDB服务器会发送提交请求;如果任何一个TiKV节点预提交失败,TiDB服务器会发送回滚请求。

在TiDB中,由于其分布式的特性,两阶段提交是一个关键的机制,用以确保数据的一致性和事务的原子性。该过程涉及到复杂的协调和通信,以确保即使在分布式环境中也能有效地处理事务。

ScyllaDB 的分布式一致性是怎么做的?

ScyllaDB,一种高性能的分布式NoSQL数据库,实现了分布式一致性,主要通过采用Apache Cassandra的一致性模型。这个模型是基于Amazon的DynamoDB设计的。ScyllaDB的分布式一致性主要通过以下几个方面来实现:

  • 数据复制(Replication):
    ScyllaDB在多个节点上复制数据,以确保高可用性和容错性。
    使用的是一种叫做“虚拟节点”的技术,它允许数据自动均匀分布在集群的所有节点上。
  • 一致性级别(Consistency Levels):
    ScyllaDB允许客户端在读写操作中选择不同的一致性级别,例如ONE(只需要一个节点响应)、QUORUM(大多数节点)、ALL(所有节点)等。
    不同的一致性级别可以平衡读写延迟、数据一致性和系统的容错能力。
  • 读写路径:
    写操作:一个写请求首先被发送到协调节点,然后根据一致性级别,协调节点负责将写操作复制到其他节点。
    读操作:读请求也是先到协调节点,然后根据选择的一致性级别,协调节点从一个或多个节点获取数据。
  • 故障恢复和一致性保证:
    ScyllaDB使用“Hinted Handoff”和“Read Repair”机制来处理节点故障和数据不一致的情况。
    “Hinted Handoff”允许暂时不可达的节点稍后接收更新。
    “Read Repair”在读操作过程中检测数据不一致,并进行修复。
  • Gossip协议:
    ScyllaDB使用Gossip协议来维护节点之间的信息同步,包括节点的状态、数据分布和集群的拓扑结构。
  • 分布式事务支持:
    ScyllaDB支持轻量级事务,使用乐观锁和基于时间戳的冲突解决机制。

通过这些机制,ScyllaDB能够在不同节点之间有效地复制和同步数据,确保即使在部分节点不可用的情况下也能维持数据的一致性和系统的高可用性。用户可以根据自己的需求和场景选择合适的一致性级别,以在性能和一致性之间做出平衡。

什么情况下都需要进行提交?数据同步是不是一样的道理?

在分布式系统中,"提交"通常指的是确认并应用一组操作或事务,确保这些操作在所有相关节点上得到一致的执行。提交的必要性和数据同步的概念虽然相关,但它们在实际应用中有所区别。以下是这两个概念的关键方面:

提交的情况

  • 分布式事务完成:在分布式数据库或系统中执行事务时,当所有参与的节点准备就绪,且满足一致性条件时,需要进行提交操作。这确保了事务的原子性和一致性。
  • 一致性保证:在任何需要保持数据一致性的操作中,如多个节点间的数据更新,提交是必要的步骤。这确保所有节点上的数据达到一致状态。
  • 系统状态变更:在某些系统中,如配置更改或重要状态更新,在所有相关节点上达成一致后需要进行提交。

数据同步

数据同步涉及保持不同系统或组件间数据的一致性。
它可能涉及以下情况:

  • 实时或定期更新:数据同步可能是实时的(如数据库复制)或按计划进行的(如定时备份)。
  • 多源一致性:在多个数据源之间同步数据时,数据同步确保所有源保持一致。
  • 故障恢复和备份:数据同步也是故障恢复和备份策略的一部分,确保数据的持久性和可用性。

相关性和区别

相关性:提交通常是数据同步过程的一部分。例如,在分布式数据库的两阶段提交协议中,提交是同步数据到所有节点的最后步骤。
区别:提交是一个决策点,表示事务或操作的完成,而数据同步是一个持>续的过程,涉及数据在节点间的持续一致性维护。

在分布式系统的设计和操作中,理解这两个概念及其相互作用是非常重要的,以确保系统的稳定性和数据的一致性。

3PC-三阶段提交

三阶段提交(Three-phase commit),也叫三阶段提交协议(Three-phase commit protocol),是二阶段提交(2PC)的改进版本。

三阶段提交示意图
在这里插入图片描述

与两阶段提交不同的是,三阶段提交有两个改动点。

1、引入超时机制。同时在协调者和参与者中都引入超时机制。
2、在第一阶段和第二阶段中插入一个**准备阶段,**保证了在最后提交阶段之前各参与节点状态的一致。

也就是说,除了引入超时机制之外,3PC把2PC的投票阶段再次一分为二,这样三阶段提交就有CanCommitPreCommitDoCommit三个阶段。

为什么要把投票阶段一分为二?
假设有1个协调者,9个参与者。其中有一个参与者不具备执行该事务的能力。

协调者发出prepare消息之后,其余参与者都将资源锁住,执行事务,写入undo和redo日志。

协调者收到相应之后,发现有一个参与者不能参与。所以,又出一个roolback消息。其余8个参与者,又对消息进行回滚。这样子,是不是做了很多无用功?

所以,引入 can-Commit 阶段,主要是为了在预执行之前,保证所有参与者都具备可执行条件,从而减少资源浪费。 减少无用功。

在这里插入图片描述

CanCommit阶段

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

1.事务询问
协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。
2.响应反馈
参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No

PreCommit阶段

本阶段协调者会根据第一阶段的询盘结果采取相应操作,询盘结果主要有两种:

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

1.发送预提交请求
协调者向参与者发送PreCommit请求,并进入Prepared阶段。
2.事务预提交
参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。
3.响应反馈
如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令。

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

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

doCommit 阶段

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

情况1-执行提交

针对第一种情况,协调者向各个参与者发起事务提交请求,具体步骤如下:

  1. 协调者向所有参与者发送事务commit通知
  2. 所有参与者在收到通知之后执行commit操作,并释放占有的资源
  3. 参与者向协调者反馈事务提交结果

在这里插入图片描述

情况2-中断事务

协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。具体步骤如下:

1.发送中断请求协调者向所有参与者发送事务rollback通知。
2.事务回滚所有参与者在收到通知之后执行rollback操作,并释放占有的资源。
3.反馈结果参与者向协调者反馈事务提交结果。
4.中断事务协调者接收到参与者反馈的ACK消息之后,执行事务的中断。

2PC与3PC的区别

三段提交协议(3PC)相对于两段提交协议(2PC)的主要改进在于它增加了一个额外的阶段,即“预提交”阶段,并通过这个阶段来减少阻塞和改善在某些失败情况下的处理。下面是两者的主要差异和3PC的改进之处:

两段提交协议(2PC)
  1. 准备阶段:协调者询问所有参与者是否可以提交事务,参与者执行事务并锁定资源后反馈是否可以提交。
  2. 提交/回滚阶段
    • 如果所有参与者都同意提交,协调者指示所有参与者提交事务。
    • 如果任何参与者反对提交,协调者指示所有参与者回滚事务。
三段提交协议(3PC)
  1. 询问阶段:与2PC的准备阶段类似,协调者询问参与者是否可以提交事务。
  2. 预提交阶段:协调者在所有参与者同意提交后,发送预提交请求。参与者锁定资源并准备提交,然后反馈准备就绪。
  3. 提交/回滚阶段
    • 在收到所有参与者的准备就绪反馈后,协调者指示提交。
    • 如果在预提交阶段有参与者无法准备就绪,协调者指示回滚。
3PC 相对 2PC 的改进之处
  1. 减少阻塞:在2PC中,如果协调者在第二阶段崩溃,参与者可能会无限期地阻塞等待协调者的指令。3PC通过引入预提交阶段,允许参与者在不接收到进一步指令的情况下安全地中止事务,从而减少了阻塞的可能性。
  2. 更好的失败处理:3PC允许在预提交阶段检测到失败,并且在事务真正提交之前安全地回滚,从而降低了部分提交的风险。
  3. 提高容错性:由于有额外的阶段来确认参与者的状态,3PC在处理网络延迟和参与者故障方面比2PC更为灵活和健壮。

尽管3PC相对于2PC有所改进,但它仍然不能完全解决所有分布式事务问题,特别是在分布式系统中面对网络分区和同时多点故障时。此外,3PC相比2PC更加复杂,可能会引入额外的开销。在实际应用中,选择哪种协议需要根据系统的特定需求和特点来决定。

3PC 当前的应用情况

三阶段提交协议(3PC)并不像两阶段提交协议(2PC)那样在商业和开源中间件或框架中广泛使用。3PC主要作为2PC的改进,用于解决在分布式系统中的一些特定问题,比如降低系统在协调者失败时的阻塞风险。然而,由于它的复杂性和在某些场景下的性能开销,3PC并没有得到广泛的实际应用。

使用场景

尽管不广泛,3PC仍然可能在一些特定场景中被采用,尤其是在那些对于系统阻塞和故障恢复有更高要求的环境。例如:

  • 高可用性系统:在需要高度可用性且不能容忍长时间锁定资源的系统中,3PC可能会被考虑。
  • 分布式数据库:一些分布式数据库系统可能会选择使用3PC来提高在网络分区或协调者故障时的容错性。
现实中的应用

在现实中,由于 3PC 仍然不能完全解决网络分区问题,并且带来了额外的复杂性和开销,许多分布式系统更倾向于使用其他技术来处理一致性和容错问题,如:

  • 容错机制:使用其他容错机制,如Paxos或Raft等一致性算法,这些算法在分布式系统中被广泛使用以提高可靠性和一致性。
  • 最终一致性模型:在某些应用中,最终一致性模型被视为一个更实用的选择,它允许系统在一段时间内达到一致状态,而不是立即一致。
主要作用

3PC 的主要作用是在分布式事务处理中提供一种比 2PC 更安全的机制,减少在协调者失败时的阻塞风险,同时试图在一定程度上提高系统在面对故障时的容错能力。

总的来说,尽管3PC在理论上是一个有吸引力的概念,但由于实际应用中的挑战,它并没有在中间件或框架中得到广泛的采用,特别是当与其他更成熟的技术相比较时。在选择分布式事务协议时,通常需要根据系统的具体需求和特性进行综合考虑。

扩展

XA 事务协调

经过上面提到的 2PC 与 3PC,我们再来介绍一个 XA 协议,
下图是 XA 协议的构造图。

XA 的全称是 “eXtended Architecture”。这个术语通常用于描述一种用于分布式事务处理的标准接口,特别是在数据库管理系统中。XA接口允许多个资源(如数据库、消息队列等)在一个全局事务中协同工作,从而提供> 跨多个系统的事务一致性和原子性。

在这里插入图片描述
可知XA规范中分布式事务有 AP,RM,TM 组成:

  • 其中应用程序(Application Program ,简称 AP):AP定义事务边界(定义事务开始和结束)并访问事务边界内的资源。
  • 资源管理器(Resource Manager,简称 RM):Rm管理计算机共享的资源,许多软件都可以去访问这些资源,资源包含比如数据库、文件系统、打印机服务器等。
  • 事务管理器(Transaction Manager ,简称 TM):负责管理全局事务,分配事务唯一标识,监控事务的执行进度,并负责事务的提交、回滚、失败恢复等。

它定义了一个双向接口(双相接口),允许全局事务管理器与局部资源管理器进行交互。这些资源管理器通常是数据库、消息队列等支持事务的系统。

XA协议的工作流程:

开始全局事务:

事务管理器(通常是一个应用服务器或事务协调器)启动一个全局事务。

分支事务:

全局事务包含多个分支事务,每个分支事务对应一个资源管理器(例如,一个数据库)。
事务管理器通知所有涉及的资源管理器参与这个全局事务。

执行本地操作:

在各个资源管理器上执行本地事务操作(如数据库更新、消息发送等)。

第一阶段 - 准备阶段:

事务管理器向所有参与的资源管理器发送准备(PREPARE)命令。
每个资源管理器将其事务操作记录到日志中,并准备提交事务,但不实际提交。
资源管理器向事务管理器报告它已准备好提交或不能提交(如果发生错> 误)。

第二阶段 - 提交/回滚:

如果所有资源管理器都准备好提交,事务管理器发出提交(COMMIT)命令,完成事务。
如果任何资源管理器报告不能提交,事务管理器将发出回滚(ROLLBACK)命令,撤销所有分支事务的操作。

结束事务:

事务最终被提交或回滚,所有资源管理器释放事务资源。

如何实现分布式事务:
  • 一致性:通过两阶段提交确保所有参与的资源管理器要么全部提交事务,要么全部回滚,从而维护事务的一致性。
  • 原子性:事务要么完全成功(即所有更改都被提交),要么完全失败(即所有更改都被撤销),确保事务的原子性。
  • 跨多个资源管理器:XA协议允许不同的资源管理器(可能是不同类型的数据库或其他事务性资源)参与到同一个全局事务中。
  • 标准化接口:XA定义了一个标准接口,使得不同的资源管理器可以以统一的方式参与全局事务,简化了分布式事务的管理。

总的来说,XA 协议通过提供一种机制来协调分布在不同资源管理器上的事务操作,确保了分布式事务的一致性和原子性。通过标准化的接口和两阶段提交的流程,XA协议成为了管理复杂分布式环境中事务的有效工具。

XA 与 2PC 和 3PC 的不同:
  • 标准化接口:XA的主要特点是它定义了资源管理器和事务管理器之间的标准接口。而2PC和3PC更多关注于事务的阶段和流程。
  • 适用性:XA更适用于将多种不同类型的数据源(如不同数据库)纳入同一个事务的场景。而2PC和3PC通常在特定的系统或技术栈中实现。

XA的关键特征:

  • 全局事务和局部事务:XA 允许在多个资源管理器上创建和管理全局事务。全局事务包含多个局部事务,每个局部事务对应一个资源管理器。
  • 两阶段提交(2PC):XA 实际上使用了2PC机制,但它提供了标准化的接口,使得不同的资源管理器可以参与到同一个全局事务中。
  • 灵活性:XA提供了灵活性,允许不同类型的资源管理器加入到事务中,只要它们支持XA协议。

为什么在单个数据源中XA不是更好的选择?

  • 复杂性和性能开销:XA协议设计用于跨多个数据源的分布式事务,其实现相对复杂。在单个数据源的场景中使用XA,会引入不必要的复杂性和性能开销。
  • 过度设计:对于单一数据源的事务,2PC或3PC已经足够有效地保证事务的一致性和原子性。在这种情况下,使用XA相当于对问题进行过度设计。
  • 资源利用:XA可能导致更高的资源消耗和更长的锁定时间,因为它需要协调多个不同的系统。在单个数据源的情况下,这种额外的资源消耗是不必要的。

为什么在多个数据源中2PC、3PC不是更好的选择?

  • 不同系统的兼容性:2PC和3PC通常在单个数据库管理系统(DBMS)内或紧密集成的系统中实现。它们不一定适用于涉及多种不同类型数据库或数据源的场景。
  • 跨系统事务管理:在多个数据源的场景中,需要协调不同系统之间的事务。XA提供了一个标准接口,使得不同系统能够共同参与到同一个分布式事务中,而2PC和3PC缺乏这种跨系统的事务协调机制。
  • 技术栈的限制:在多数据源环境中,不同数据源可能使用不同的技术栈,这可能导致在使用2PC或3PC时遇到兼容性问题。XA通过定义标准接口,更容易在这样的多样化环境中实现事务管理。

引用

分布式一致性之两阶段提交协议、三阶提交协议
凤凰架构
chatgpt4

  • 18
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值