先来露怯一波:记得我工作年在做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,顾名思义,整个过程一共分为两个阶段,即
投票表决阶段 提交阶段
阶段主要分为3个小步骤
TM发起事务询问 事务管理器(协调者)向所有的资源管理器(参与者)发送事务处理请求,并开始等待各资源管理器的响应。 RM执行本地事务(不提交) 各个资源管理器(参与者)执行本地事务操作,但在执行完成后并不会真正的进行提交本地事务 各RM向TM进行反馈 各个资源管理器(参与者)会向事务管理器(协调者)回复是否已经做好准备,如果执行本地事务成功,就反馈YES;如果 执行本地事务失败,就反馈NO。
此时在阶段执行完成后,会面临两个结果
A、存在资源管理器(参与者)向事务管理器(协调者)反馈NO B、所有资源管理器(参与者)都向事务管理器(协调者)反馈的YES
第二阶段分为2个小步骤
如果阶段结果为A,则作为异常处理。
事务管理器(协调者)会通知所有的资源管理器(参与者)进行Rollack回滚处理 资源管理器(参与者)会进行本地事务的回滚
如果阶段结果为,即资源管理器(参与者)全部反馈的A,则作为正常处理。
事务管理器(协调者)会通知所有的资源管理器(参与者)进行Commit提交处理 资源管理器(参与者)会进行本地事务的提交
无论第二阶段是异常回滚还是正常提交,都标志着当前事务的结束
2PC的缺陷
2PC虽然将XA规范方案细化成思路,也形成了流程图,大部情况下确实能提供原子性操作,但是缺存在着几个问题:
同步阻塞影响性能 整个2PC的过程中,无论事务管理器(协调者)还是资源管理器(参与者)都是事务阻塞型的,这期间公共资源会一直持有并锁定,其他操作想持有资源,必须等待必须等待原事务的第二阶段结束,导致性能下降,因此2PC不适合高并发场景
解决方案:引入超时机制
事务管理器(协调者)单点问题 事务管理器(协调者)在二阶段还没有发送指令前宕机,这时所有资源管理器(参与者)都会陷入阻塞情况;
解决方案:引入事务管理器(协调者)的HA选举的机制;同时事务管理器(协调者)会在操作先留下checkpoint,当检测到事务管理器(协调者)宕机一段时间后,事务管理器(协调者)会进行重新选举,之后读取操作checkpoint,并向所有资源管理器(参与者)进行问询,恢复原事务流程进度。
数据不一致 事务管理器(协调者)在二阶段发送指令后宕机,部分资源管理器(参与者)执行提交或者回滚成功,部分因为自身原因或者网络问题没有收到指令从而执行失败,会出现数据不一致的情况
解决方案:资源管理器(参与者)引入重试机制;资源管理器(参与者)之间的加入互相通信机制;当资源管理器(参与者)在二阶段提交本地事务失败后,为了保证事务的原子性,需要再通知事务管理器(协调者),然后再次给所有资源管理器(参与者)广播中断事务
事务执行进度丢失 当事务管理器(协调者)在二阶段发送指令后宕机,而接受到信息的资源管理器(参与者)在执行本地事务后也宕机了,当后续事务管理器(协调者)恢复后和资源管理器(参与者),无法得知是否已经执行事务。
3PC
3PC全称是Three-phaseCommit,也就是我们俗称的三段式提交, 3PC的提出主要是在2PC的基础上进行改良,为了解决两段式提交协议的同步阻塞问题,2PC存在的问题是当事务管理器(协调者)崩溃或者宕机的时候,资源管理器(参与者)不能做出后的选择。因此资源管理器(参与者)会在协作者事务管理器(协调者)保持阻塞。
3PC整体流程如下图所示:
CanCommit阶段
3PC的CanCommit阶段其实和2PC的准备阶段很像。
事务管理器(协调者)向资源管理器(参与者)发送CanCommit请求 资源管理器(参与者)如果认为自身具备事务提交的可能就返回Yes响应,否则返回No响应,不进行实际的动作,并不会锁定资源。
PreCommit阶段
事务管理器(协调者)根据资源管理器(参与者)在CanCommit阶段的反馈情况来确定时候需要继续下一步,执行PreCommit操作。
阶段完成后会面临两种情况:
Result-A: 所有的资源管理器(参与者)反馈的都是Yes
事务管理器(协调者)向所有的资源管理器(参与者)发送PreCommit请求 资源管理器(参与者)会执行事务操作,但不进行事务提交,同时将undo和redo信息记录到事务日志中,对资源进行加锁, 资源管理器(参与者)本地事务执行完成后向事务管理器(协调者)进行返回ACK
Result-B: 资源管理器(参与者)反馈中的存在No,或者超时时间内没有收到响应
事务管理器(协调者)向所有的资源管理器(参与者)发送事务中断的abort请求 资源管理器(参与者)收到abort请求后开始,执行事务的中断。若在超时时间内没有收到来自事务管理器(协调者),同样进行执行中断
DoCommit阶段
该阶段进行真正的事务提交,即对所有资源进行释放,也涉及到两种情况
阶段完成后会面临两种情况:
Result-A: 所有的资源管理器(参与者)都有反馈ACK
事务管理器(协调者)在PreCommit阶段接收到资源管理器(参与者)发送的ACK响应,向所有资源管理器(参与者)发送doCommit请求 资源管理器(参与者)接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。 资源管理器(参与者)在事务提交完之后,向事务管理器(协调者)发送Ack响应。 事务管理器(协调者)协接收到所有资源管理器(参与者)的ack响应之后,完成事务。
Result-B: 资源管理器(参与者)在超时时间内没有反馈ACK
事务管理器(协调者)向所有资源管理器(参与者)发送abort请求 资源管理器(参与者)接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。 资源管理器(参与者)完成事务回滚之后,向事务管理器(协调者)发送ACK消息 事务管理器(协调者)接收到资源管理器(参与者)反馈的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了。