分布式事物

一、什么事分布式事物?

分布式事物,就是在分布式系统中运行的事物,由多个本地事物组成。在分布式场景下,事物可能来自与不同的系统,不同的集群。

分布式事物的基本特性
  分布式事物是由多个事物的组合,那么,事物的特征ACID也就是分布式事务的基本特征。

原子性(Atomicity),即事务最终的状态只有两种,全部执行成功和全部不执行。若处理事务的任何一项操作不成功,就会导致整个事务失败。一旦操作失败,所有操作都会被取消(即回滚),使得事务仿佛没有被执行过一样。

一致性(Consistency),是指事务操作前和操作后,数据的完整性保持一致或满足完整性约束。

隔离性(Isolation),是指当系统内有多个事务并发执行时,多个事务不会相互干扰,即一个事务内部的操作及使用的数据,对其他并发事务是隔离的。

持久性(Durability),也被称为永久性,是指一个事务完成了,那么它对数据库所做的更新就被永久保存下来了。即使发生系统崩溃或宕机等故障,只要数据库能够重新被访问,那么一定能够将其恢复到事务完成时的状态。

二、如何实现分布式事物?

目前,实现分布式事物主要有以下三种方式:

  • 基于 XA 协议的二阶段提交协议方法;
  • 三阶段提交协议方法;
  • 基于消息中间件的最终一致性方法。
1、基于XA的二阶段提交

  XA可以分为两部分,事物管理器和资源管理器接口。事务管理器作为协调者,负责各个本地资源的提交和回滚;而资源管理器就是分布式事务的参与者,通常由数据库实现,比如 Oracle、DB2 等商业数据库都实现了 XA 接口。

  基于 XA 协议的二阶段提交方法中,二阶段提交协议(The two-phase commitprotocol,2PC),用于保证分布式系统中事务提交时的数据一致性,是 XA 在全局事务中用于协调多个资源的机制。

  二阶段提交协议分为投票(voting)和提交(commit)两个阶段;

  投票阶段:协调者(Coordinator,即事务管理器)会向事务的参与者(Cohort,即本地资源管理器)发起执行操作的 CanCommit 请求,并等待参与者的响应。参与者接收到请求后,会执行请求中的事务操作,记录日志信息但不提交,待参与者执行成功,则向协调者发送“Yes”消息,表示同意操作;若不成功,则发送“No”消息,表示终止操作。

  提交阶段。在提交阶段,协调者会根据所有参与者返回的信息向参与者发送 DoCommit 或 DoAbort 指令:

  若协调者收到的都是“Yes”消息,则向参与者发送“DoCommit”消息,参与者会完成剩余的操作并释放资源,然后向协调者返回“HaveCommitted”消息;

  如果协调者收到的消息中包含“No”消息,则向所有参与者发送“DoAbort”消息,此时发送“Yes”的参与者则会根据之前执行操作时的回滚日志对操作进行回滚,然后所有参与者会向协调者发送“HaveCommitted”消息;协调者接收到“HaveCommitted”消息,就意味着整个事务结束了。

虽然基于 XA 的二阶段提交算法基本满足了事务的 ACID 特性,但依然有些不足。

同步阻塞问题:二阶段提交算法在执行过程中,所有参与节点都是事务阻塞型的。也就是说,当本地资源管理器占有临界资源时,其他资源管理器如果要访问同一临界资源,会处于阻塞状态。

单点故障问题:基于 XA 的二阶段提交算法类似于集中式算法,一旦事务管理器发生故障,整个系统都处于停滞状态。尤其是在提交阶段,一旦事务管理器发生故障,资源管理器会由于等待管理器的消息,而一直锁定事务资源,导致整个系统被阻塞。

数据不一致问题:在提交阶段,当协调者向参与者发送 DoCommit 请求之后,如果发生了局部网络异常,或者在发送提交请求的过程中协调者发生了故障,就会导致只有一部分参与者接收到了提交请求并执行提交操作,但其他未接到提交请求的那部分参与者则无法执行事务提交。于是整个分布式系统便出现了数据不一致的问题。

4、三阶段提交方法

  三阶段提交协议(Three-phase commit protocol,3PC),是对二阶段提交(2PC)的改进。为了解决两阶段提交的同步阻塞和数据不一致问题,三阶段提交引入了超时机制和准备阶段。

  CanCommit阶段,CanCommit 阶段与 2PC 的投票阶段类似:协调者向参与者发送请求操作(CanCommit请求),询问参与者是否可以执行事务提交操作,然后等待参与者的响应;参与者收到CanCommit 请求之后,回复 Yes,表示可以顺利执行事务;否则回复 No。

  PreCommit阶段,协调者根据参与者的回复情况,来决定是否可以进行 PreCommit 操作。

如果所有参与者回复的都是“Yes”,那么协调者就会执行事务的预执行:
  发送预提交请求。协调者向参与者发送 PreCommit 请求,进入预提交阶段。
  事务预提交。参与者接收到 PreCommit 请求后执行事务操作,并将 Undo 和 Redo信息记录到事务日志中。
  响应反馈。如果参与者成功执行了事务操作,则返回 ACK 响应,同时开始等待最终指令。

假如任何一个参与者向协调者发送了“No”消息,或者等待超时之后,协调者都没有收到参与者的响应,就执行中断事务的操作:
  发送中断请求。协调者向所有参与者发送“Abort”消息。
  终断事务。参与者收到“Abort”消息之后,或超时后仍未收到协调者的消息,执行事务的终断操作。

  预执行阶段,不同节点上事务执行成功和失败的流程,如下所示。

  DoCmmit 阶段进行真正的事务提交,根据 PreCommit 阶段协调者发送的消息,进入执行提交阶段或事务中断阶段。

执行提交阶段:
  **发送提交请求。协调者接收到所有参与者发送的 Ack 响应,从预提交状态进入到提交状态,并向所有参与者发送 DoCommit 消息。
  事务提交。参与者接收到 DoCommit 消息之后,正式提交事务。完成事务提交之后,释放所有锁住的资源。
  响应反馈。参与者提交完事务之后,向协调者发送 Ack 响应。完成事务。协调者接收到所有参与者的 Ack 响应之后,完成事务。

事务中断阶段:
  发送中断请求。协调者向所有参与者发送 Abort 请求。
  事务回滚。参与者接收到 Abort 消息之后,利用其在 PreCommit 阶段记录的 Undo信息执行事务的回滚操作,并释放所有锁住的资源。
  反馈结果。参与者完成事务回滚之后,向协调者发送 Ack 消息。
  终断事务。协调者接收到参与者反馈的 Ack 消息之后,执行事务的终断,并结束事务。

  执行阶段不同节点上事务执行成功和失败 (事务终断) 的流程,如下所示。在 DoCommit 阶段,当参与者向协调者发送 Ack 消息后,如果长时间没有得到协调者的响应,在默认情况下,参与者会自动将超时的事务进行提交,不会像两阶段提交那样被阻塞住

3、基于分布式消息的最终一致性方案

  2PC 和 3PC 这两种方法,有两个共同的缺点,一是都需要锁定资源,降低系统性能;二是,没有解决数据不一致的问题。因此,便有了通过分布式消息来确保事务最终一致性的方案。

  在 eBay 的分布式系统架构中,架构师解决一致性问题的核心思想就是:将需要分布式处理的事务通过消息或者日志的方式异步执行,消息或日志可以存到本地文件、数据库或消息队列中,再通过业务规则进行失败重试。这个案例,就是使用基于分布式消息的最终一致性方案解决了分布式事务的问题。终断事务。协调者接收到参与者反馈的 Ack 消息之后,执行事务的终断,并结束事务。

引用:极客时间读书笔记

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值