架构师必知必会之分段式提交|推荐收藏


先来露怯一波:记得我工作年在做DBA的时候,周末去一个培训机构听数据库相关的讲座,当时提到了广义上分布式事务的问题,旁边一个地中海的老哥,脱口而出两段式提交。当时的我并不太了解这个知识点,网上也搜了下资料,瞬间崩溃,完全看不懂。感叹当初要是有那么一套系列文章该有多好。

在上一篇分布式事务中,我们了解到了什么是分布式事务,分布式事务的分类有哪些。在解决方案上,分布式事务分为刚性事务和柔性事务。

这里我们趁着这个机会重点讲一下刚性事务,顺便解一下当年之痛。

刚性事务

刚性事务是指从底层服务端的解决方案,业务并不需要在业务层面做逻辑调整。实现的是强一致性,但由于同步阻塞的问题,导致并发性差,因此适合短事务。在刚性事务中代表方案为2PC、3PC即两段式提交和三段式提交。

XA协议


在提及分段式提交之前,我们先介绍下XA协议。XA协议是在1994年由Tuxedo提出的,并且提交给X/Open组织,在XA协议提出之后,各大主流的数据库产品也纷纷提供了对XA协议的支持,比如Oracle、MySQL、DB2等

XA协议定义了接口标准,打通资源管理器(RM)与事务管理器(TM)的通信过程,从而更好的管理分布式事务,为了不影响后续的阅读,我再重新简单介绍下RM和TM的定义。更全面的介绍,请参考上一篇《啥?分布式啥?啥事务?

  • 资源管理器(Resource Manager):用来管理系统资源,是通向事务资源的途径。数据库也是RM,每个RM管理着本地事务。
  • 事务管理器(Transaction Manager):事务管理器是分布式事务的核心管理者。协调各个资源管理器,完成事务处理。

前面提到的2PC、3PC就是XA协议的衍生品。

2PC


2PC全称是Two-phaseCommit,也就是我们俗称的二段式提交,2PC是一个非常经典的强一致、中心化的原子提交协议。网上很多资料在介绍2PC的时候会重新定义协调者(coordinator)和参与者(participants)的角色,这也是为啥大家会蒙的原因之一,实际上这里的协调者和参与者就是对应的事务管理器Transaction Manager和资源管理器Resource Manager。

2PC,顾名思义,整个过程一共分为两个阶段,即

  1. 投票表决阶段
  2. 提交阶段
2PC阶段

阶段主要分为3个小步骤

  1. TM发起事务询问 事务管理器(协调者)向所有的资源管理器(参与者)发送事务处理请求,并开始等待各资源管理器的响应。
  2. RM执行本地事务(不提交) 各个资源管理器(参与者)执行本地事务操作,但在执行完成后并不会真正的进行提交本地事务
  3. 各RM向TM进行反馈 各个资源管理器(参与者)会向事务管理器(协调者)回复是否已经做好准备,如果执行本地事务成功,就反馈YES;如果 执行本地事务失败,就反馈NO。

此时在阶段执行完成后,会面临两个结果

  • A、存在资源管理器(参与者)向事务管理器(协调者)反馈NO
  • B、所有资源管理器(参与者)都向事务管理器(协调者)反馈的YES

第二阶段分为2个小步骤

如果阶段结果为A,则作为异常处理。

  1. 事务管理器(协调者)会通知所有的资源管理器(参与者)进行Rollack回滚处理
  2. 资源管理器(参与者)会进行本地事务的回滚

如果阶段结果为,即资源管理器(参与者)全部反馈的A,则作为正常处理。

  1. 事务管理器(协调者)会通知所有的资源管理器(参与者)进行Commit提交处理
  2. 资源管理器(参与者)会进行本地事务的提交

无论第二阶段是异常回滚还是正常提交,都标志着当前事务的结束

2PC的缺陷

2PC虽然将XA规范方案细化成思路,也形成了流程图,大部情况下确实能提供原子性操作,但是缺存在着几个问题:

  1. 同步阻塞影响性能 整个2PC的过程中,无论事务管理器(协调者)还是资源管理器(参与者)都是事务阻塞型的,这期间公共资源会一直持有并锁定,其他操作想持有资源,必须等待必须等待原事务的第二阶段结束,导致性能下降,因此2PC不适合高并发场景
  • 解决方案:引入超时机制
  1. 事务管理器(协调者)单点问题 事务管理器(协调者)在二阶段还没有发送指令前宕机,这时所有资源管理器(参与者)都会陷入阻塞情况;
  • 解决方案:引入事务管理器(协调者)的HA选举的机制;同时事务管理器(协调者)会在操作先留下checkpoint,当检测到事务管理器(协调者)宕机一段时间后,事务管理器(协调者)会进行重新选举,之后读取操作checkpoint,并向所有资源管理器(参与者)进行问询,恢复原事务流程进度。
  1. 数据不一致 事务管理器(协调者)在二阶段发送指令后宕机,部分资源管理器(参与者)执行提交或者回滚成功,部分因为自身原因或者网络问题没有收到指令从而执行失败,会出现数据不一致的情况
  • 解决方案:资源管理器(参与者)引入重试机制;资源管理器(参与者)之间的加入互相通信机制;当资源管理器(参与者)在二阶段提交本地事务失败后,为了保证事务的原子性,需要再通知事务管理器(协调者),然后再次给所有资源管理器(参与者)广播中断事务
  1. 事务执行进度丢失 当事务管理器(协调者)在二阶段发送指令后宕机,而接受到信息的资源管理器(参与者)在执行本地事务后也宕机了,当后续事务管理器(协调者)恢复后和资源管理器(参与者),无法得知是否已经执行事务。

3PC

3PC全称是Three-phaseCommit,也就是我们俗称的三段式提交, 3PC的提出主要是在2PC的基础上进行改良,为了解决两段式提交协议的同步阻塞问题,2PC存在的问题是当事务管理器(协调者)崩溃或者宕机的时候,资源管理器(参与者)不能做出后的选择。因此资源管理器(参与者)会在协作者事务管理器(协调者)保持阻塞。

3PC整体流程如下图所示:

3PC整体流程

CanCommit阶段

3PC的CanCommit阶段其实和2PC的准备阶段很像。

  1. 事务管理器(协调者)向资源管理器(参与者)发送CanCommit请求
  2. 资源管理器(参与者)如果认为自身具备事务提交的可能就返回Yes响应,否则返回No响应,不进行实际的动作,并不会锁定资源。

PreCommit阶段

事务管理器(协调者)根据资源管理器(参与者)在CanCommit阶段的反馈情况来确定时候需要继续下一步,执行PreCommit操作。

阶段完成后会面临两种情况:

Result-A: 所有的资源管理器(参与者)反馈的都是Yes

  1. 事务管理器(协调者)向所有的资源管理器(参与者)发送PreCommit请求
  2. 资源管理器(参与者)会执行事务操作,但不进行事务提交,同时将undo和redo信息记录到事务日志中,对资源进行加锁,
  3. 资源管理器(参与者)本地事务执行完成后向事务管理器(协调者)进行返回ACK

Result-B: 资源管理器(参与者)反馈中的存在No,或者超时时间内没有收到响应

  1. 事务管理器(协调者)向所有的资源管理器(参与者)发送事务中断的abort请求
  2. 资源管理器(参与者)收到abort请求后开始,执行事务的中断。若在超时时间内没有收到来自事务管理器(协调者),同样进行执行中断

DoCommit阶段

该阶段进行真正的事务提交,即对所有资源进行释放,也涉及到两种情况

阶段完成后会面临两种情况:

Result-A: 所有的资源管理器(参与者)都有反馈ACK

  1. 事务管理器(协调者)在PreCommit阶段接收到资源管理器(参与者)发送的ACK响应,向所有资源管理器(参与者)发送doCommit请求
  2. 资源管理器(参与者)接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。
  3. 资源管理器(参与者)在事务提交完之后,向事务管理器(协调者)发送Ack响应。
  4. 事务管理器(协调者)协接收到所有资源管理器(参与者)的ack响应之后,完成事务。

Result-B: 资源管理器(参与者)在超时时间内没有反馈ACK

  1. 事务管理器(协调者)向所有资源管理器(参与者)发送abort请求
  2. 资源管理器(参与者)接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。
  3. 资源管理器(参与者)完成事务回滚之后,向事务管理器(协调者)发送ACK消息
  4. 事务管理器(协调者)接收到资源管理器(参与者)反馈的ACK消息之后,执行事务的中断。

在2PC的基础上,3PC主要优化了上面提到1、2、4问题:

  • 在事务管理器(协调者)和资源管理器(参与者)之间都引入了超时机制。这里注意在资源管理器(参与者)向事务管理器(协调者)返回信息时,如若超时均会被认为失败,执行中断或回滚事务的流程;而在DoCommit阶段中,资源管理器(参与者)即使在超时时间内没有收到事务管理器(协调者)的信息,也会进行本地的事务提交处理;这样就解决了同步阻塞时间长的问题。但如果事务管理器(协调者)执行的是Abort请求,但资源管理器(参与者)在网络阻塞或其他原因没有收到信息,也会执行Commit操作,这样又引入了新的数据不一致问题。

  • 3PC对2PC的个阶段进行了拆分,得到CanCommit阶段、PreCommit阶段、DoCommit阶段,3PC的CanCommit阶段并不会持有资源,如果事务管理器(协调者)宕机也降低范围会降低;

  • 对于事务管理器(协调者)和资源管理器(参与者)都宕机,引发事务执行进度丢失的问题,3PC中当事务管理器(协调者)恢复(选举机制暂时不过多解释)时,会询问其他的资源管理器(参与者)事务执行进度,这里其他节点要么是Commit阶段,要么是PreCommit阶段或者是Rollback阶段。

2PC && 3PC总结

2PC和3PC一般应用于数据库当中,但2PC和3PC也不是银弹,并不适合高并发的场景。

并且无论是哪一个都不能彻底解决分布式系统一致性的问题,有数据一致性的隐患存在。

Google Chubby的作者Mike Burrows说过, there is only one consensus protocol, and that’s Paxos” – all other approaches are just broken versions of Paxos. 意即:世上只有一种一致性算法,那就是Paxos,看来真的需要后续我们研究一下Paxos了。


相关文章