分布式事务的那点事

在一系列微服务系统当中,假如不存在分布式事务,会发生什么呢?以互联网中经常使用的交易业务为例子:数据库

上图中包含了库存和订单两个独立的微服务,每一个微服务维护了本身的数据库。在交易系统的业务逻辑中,一个商品在下单以前须要先调用库存服务,进行扣除库存,再调用订单服务,建立订单记录。网络

正常状况下,两个数据库各自更新成功,两边数据维持着一致性。异步

可是,在非正常状况下,有可能库存的扣减完成了,随后的订单记录却由于某些缘由插入失败。这个时候,两边数据就失去了应有的一致性。分布式

这种时候必需要保证数据的一致性。单数据源的一致性依靠单机事务来保证,多数据源的一致性就要依靠分布式事务微服务

那么,什么是分布式事务呢?性能

分布式事务用于在分布式系统中保证不一样节点之间的数据一致性。分布式事务的实现有不少种,最具备表明性的是由Oracle Tuxedo系统提出的XA分布式事务协议。spa

XA协议包含两阶段提交(2PC)三阶段提交(3PC)两种实现,这里重点介绍两阶段提交的具体过程。3d

若是玩过魔兽世界的朋友应该知道,XA协议的运做方式和魔兽世界中的团队协做有些类似。在魔兽世界这款游戏中,副本组团打BOSS的时候,为了更方便队长与队员们之间的协做,队长能够发起一个“就位确认”的操做:中间件

当队员收到就位确认提示后,若是已经就位,就选择“是”,若是还没就位,就选择“否”。blog

当队长收到了全部人的就位确认,就会向全部队员们发布消息,告诉他们开始打BOSS。

相应的,在队长发起就位确认的时候,有可能某些队员尚未就位:

以上就是魔兽世界当中组团打BOSS的确认流程。这个流程和XA分布式事务协议的两阶段提交很是类似。

那么XA协议到底是什么样子呢?在XA协议中包含着两个角色:事务协调者事务参与者。来看一看他们之间的交互流程:

第一阶段:

在XA分布式事务的第一阶段,做为事务协调者的节点会首先向全部的参与者节点发送Prepare请求。

在接到Prepare请求以后,每个参与者节点会各自执行与事务有关的数据更新,写入Undo Log和Redo Log。若是参与者执行成功,暂时不提交事务,而是向事务协调节点返回“完成”消息。

当事务协调者接到了全部参与者的返回消息,整个分布式事务将会进入第二阶段。

第二阶段:

在XA分布式事务的第二阶段,若是事务协调节点在以前所收到都是正向返回,那么它将会向全部事务参与者发出Commit请求。

接到Commit请求以后,事务参与者节点会各自进行本地的事务提交,并释放锁资源。当本地事务完成提交后,将会向事务协调者返回“完成”消息。

当事务协调者接收到全部事务参与者的“完成”反馈,整个分布式事务完成。

以上所描述的是XA两阶段提交的正向流程,接下来看一看失败状况的处理流程:

第一阶段:

第二阶段:

在XA的第一阶段,若是某个事务参与者反馈失败消息,说明该节点的本地事务执行不成功,必须回滚。

因而在第二阶段,事务协调节点向全部的事务参与者发送Abort请求。接收到Abort请求以后,各个事务参与者节点须要在本地进行事务的回滚操做,回滚操做依照Undo Log来进行。

以上就是XA两阶段提交协议的详细过程。

XA两阶段提交虽然解决了分布式事务的一致性问题,可是仍然存在着不少不足之处。

XA两阶段提交究竟有哪些不足呢?

1.性能问题

XA协议遵循强一致性。在事务执行过程当中,各个节点占用着数据库资源,只有当全部节点准备完毕,事务协调者才会通知提交,参与者提交后释放资源。这样的过程有着很是明显的性能问题。

2.协调者单点故障问题

事务协调者是整个XA模型的核心,一旦事务协调者节点挂掉,参与者收不到提交或是回滚通知,参与者会一直处于中间状态没法完成事务。

3.丢失消息致使的不一致问题。

在XA协议的第二个阶段,若是发生局部网络问题,一部分事务参与者收到了提交消息,另外一部分事务参与者没收到提交消息,那么就致使了节点之间数据的不一致。

如何避免XA两阶段提交的种种问题呢?有许多其余的分布式事务方案可供选择:

1.XA三阶段提交

XA三阶段提交在两阶段提交的基础上增长了CanCommit阶段,而且引入了超时机制。一旦事物参与者迟迟没有接到协调者的commit请求,会自动进行本地commit。这样有效解决了协调者单点故障的问题。可是性能问题和不一致的问题仍然没有根本解决。

2.MQ事务

利用消息中间件来异步完成事务的后一半更新,实现系统的最终一致性。这个方式避免了像XA协议那样的性能问题。

3.TCC事务

TCC事务是Try、Commit、Cancel三种指令的缩写,其逻辑模式相似于XA两阶段提交,可是实现方式是在代码层面来人为实现。

相关文章
相关标签/搜索