MySQL学习笔记事务篇:分布式事务之2PC和3PC

目录

 

背景

二阶段提交协议

阶段一

阶段二

执行事务提交

中断事务

扩展讨论

三阶段提交协议

阶段一

阶段二

执行事务预提交

中断事务

阶段三

执行提交

中断事务

扩展讨论

总结


背景

本地事务通过ACID特性能够很好地解决原子性、一致性以及隔离性问题,然而当今大部分的软件架构对系统都有扩展的诉求,系统扩展引发了资源的分布,分布的资源可以很好地支持系统的可伸缩性,但是也同时带来分布式一致性问题,避免太过抽象,我们可以通过一个场景理解这个问题:一个完整的业务流程(全局事务)涉及分布在不同资源管理器(如:数据库)中的资源(如表记录)的状态变更,如何保证这些分布在不同资源管理器中的资源状态要么都变,要么都不变。

在分布式系统中,每一个机器节点虽然都能够明确地知道自己在进行事务操作过程中的结果是成功或失败,但是却无法直接知道其他节点的操作结果,因为他们只是全局事务中的一个参与者,因此为了尽可能解决“知道”这件事情从而对全局事务有个全局把控,一种方案是引入一个称为“协调者”的第三者来统一调度所有分布式节点的执行逻辑(注意:这同时也带来了单点问题,调度者不可用怎么办?),这些被调度的节点被称为“参与者”,因为协调者是站在全局角度,因此协调者“知道”全局事务能否提交,本文重点讨论基于“协调者”机制衍生的二阶段提交协议(2PC)和三阶段提交协议(3PC),希望通过讨论得到的产出是理解2PC和2PC的区别和优缺点以及本质区别其中对于协议的阐述部分是客观的,可能网络上有不同版本,重点是基于当前版本展开讨论

 

二阶段提交协议

二阶段提交协议是为了使基于分布式系统架构下的所有节点在进行事务处理过程中能够保持原子性和一致性而设计的算法,目前绝大部分的关系型数据库都是采用二阶段提交协议来完成分布式事务的,使用该协议来协调全局事务的参与者基于协调者统一决定是否提交事务,能够在一定程度上保证数据的一致性,因此该协议被广泛应用,二阶段协议是将事务的提交过程分为两个阶段来进行处理的。

阶段一

1、事务询问

协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者响应。

2、执行事务

各个参与者节点执行事务操作,资源管理器此时会将undo日志和redo日志计入事务日志中。

3、参与者响应协调者

如果参与者成功执行了事务操作,那么就反馈给协调者Yes响应,表示事务可以执行;如果参与者没有成功执行事务,那么就反馈给协调者No响应,表示事务不可以执行。

阶段二

在阶段二中,协调者会根据各个参与者的反馈情况来决定最终是否可以进行事务提交,正常情况下包括下面两种可能:

执行事务提交

假如所有参与者都向协调者反馈了Yes响应,则正常步骤如下:

1、发送提交请求

协调者向所有参与者发出Commit请求。

2、提交事务

参与者接收到来自协调者的Commit请求之后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期间占用的事务资源。

3、反馈事务提交

参与者在完成事务提交之后,向协调者发送Ack消息。

4、完成事务

协调者接收到所有参与者反馈的Ack消息后,完成事务。

中断事务

假如任何一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无法接收到所有参与者的反馈响应,那么就中断事务。

1、发送回滚请求

协调者向所有参与者节点发出Rollback请求。

2、事务回滚

参与者接收到Rollback请求后,会利用其在阶段一种记录的undo日志来进行回滚操作,并且完成回滚之后释放事务资源。

3、反馈事务回滚操作

参与者在完成事务回滚之后,向协调者发送Ack消息。

4、中断事务

协调者接收到所有参与者反馈的Ack消息后,完成事务中断。

扩展讨论

网络中存在各种不确定性,其中协议流程是基于时间顺序的(时间),而协议又涉及到不同的参与者(空间),时空交错,任一点都有可能出现意外,因此我们可以通过时间和空间对协议流程进行展开讨论:

阶段一:协调者出问题、参与者正常

假设只有部分节点收到协调者的询问并给予协调者反馈了,协调者此时除了问题,无法继续询问,这些部分已经参与询问的参与者可以放弃事务,相当于全局事务回滚。

阶段一:协调者正常、部分参与者出问题

假设有一部分参与者不可用,表现为无法响应或者响应No,协调者知道这件事情,因此可以通知其他参与者放弃事务,同时其他事务也可以自行放弃事务,相当于全局事务回滚。

阶段一:协调者和参与者都出问题

假设部分正常的参与者如果接受过询问,此时协调者出问题了,其他部分参与者也出问题了,则正常已经参与过询问的参与者可以放弃事务,相当于全局事务回滚。

阶段二:协调者出问题、参与者正常;

假设进入第二阶段,部分参与者已经提交了,此时协调者出问题了,此时部分提交的参与者,造成了全局状态的不一致的问题。

阶段二:协调者正常、参与者出问题

假设进入第二阶段,协调者通知完部分参与者提交了之后发现另一部分参与者不可用,此时一部分参与者已经提交了,造成了全局状态的不一致问题。

阶段二:协调者和参与者都出问题

此时部分提交的事务仍然造成了全局状态的不一致。

上面可以看出在2PC进入第二阶段之后,无论是协调者出问题还是参与者出问题,都会造成全局资源状态的不一致问题,那么为什么会造成这种问题呢?比如协调者出问题了、部分参与者已经提交的情况,其余未提交的参与者并不知道这部分已经提交的参与者是什么状况,因为对于这部分未提交的参与者来说,协调者已经跪了,它们无法知道全局事务的状态,而且剩下的参与者的状况有以下三种可能:

  1. 剩下的参与者还未参与询问

  2. 剩下的参与者已经参与询问但是还没提交

  3. 剩下的参与者已经提交

因为有太多不确定性,因此对于这部分未提交的参与者来说什么都不能做,因为做什么都是错的,结果就是出现了全局状态的一致性问题,那么从这个角度上来讲,三阶段提交协议减少这种不确定性,后面会讲到。


三阶段提交协议

三阶段提交协议是二阶段提交协议的改进版,其将二阶段提交协议的提交事务请求又分为两个阶段,形成了由CanCommit、PreCommit、DoCommit三个阶段组成的事务处理协议。

阶段一

1、事务询问

协调者向所有的参与者发送一个包含事务内容的CanCommit请求,询问是否可以执行事务提交操作,并开始等待各个参与者的响应。

2、参与者反馈

参与者在接收到来自协调者的CanCommit请求后,正常情况下,如果其自身认为可以顺利执行事务,那么会反馈Yes响应,并进入预备状态,否则反馈No响应。

阶段二

在阶段二中协调者会根据各个参与者的反馈情况来决定是否可以进行事务的PreCommit操作,正常情况下包含两种可能。

执行事务预提交

假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务预提交。

1、发送预提交请求

协调者向所有参与者节点发出PreCommit的请求,并进入Prepared阶段。

2、事务预提交

参与者接收到PreCommit请求后,会执行事务操作,资源管理器会将undo和redo信息记录到事务日志中。

3、参与者响应协调者

如果参与者成功地执行了事务,那么就反馈给协调者Ack响应,同时等待最终的指令,提交或中止。

中断事务

假如任何一个参与者向协调者反馈了No响应,或者在等待超时之后,协调者尚无法收到所有参与者的反馈响应,那么就会中止事务。

1、发送中断请求

协调者向所有参与者节点发出abort请求

2、中断事务

无论是收到来自协调者的abort请求或是在等待协调者请求过程中出现超时,参与者都会中断事务。

阶段三

该阶段进行真正的事务提交,会存在以下两种可能的情况。

执行提交

1、发送提交请求

进入这一阶段,假设协调者处于正常工作状态,并且它接受到了来自所有参与者的Ack响应,那么它将从“预提交”状态转换为“提交”状态,并向所有参与者发送DoCommit请求。

2、事务提交

参与者接收到DoCommit请求后,会正式执行事务提交操作,并且在完成提交之后释放在整个事务执行期间占用的事务资源。

3、反馈提交结果

参与者在完成提交之后,向协调者发送Ack消息。

4、完成事务

协调者接收到所有参与者反馈的Ack消息后,完成事务。

中断事务

进入这一阶段,假设协调者处于正常工作的状态,并且有任意一个参与者向协调者反馈了No响应,或在等待超时之后协调者尚无法获取所有参与者的响应。

1、发送中断请求

协调者向所有的参与者阶段发送abort请求。

2、事务回滚

参与者接收到abort请求之后,会利用其在第二阶段中记录的undo信息来执行事务回滚操作,并在完成回滚之后释放整个事务执行期间所占用的资源。

3、反馈事务回滚结果

参与者在完成回滚之后向协调者发送Ack消息。

4、中断事务

协调者接收到所有参与者反馈的Ack消息之后中断事务。

扩展讨论

这里我们主要讨论第三阶段出现问题的情况,如果读者有兴趣可以按照这种方式自行讨论第一阶段与第二阶段的问题:

阶段三:协调者出问题、参与者正常

假设一部分参与者已经提交了,此时协调者出问题,另外的一部分参与者处于已经预提交但是未提交状态,那么它们是否能提交呢?因为对于这部分参与者来说,它们至少“知道”其它参与者一定是参与询问过的,而询问的意义在于确定当前参与者能否正确执行事务,因此这部分参与者基于对于这种意义的理解,提交事务,全局资源状态一致。

阶段三:协调者正常、参与者出问题和协调者和参与者都出问题

这种两种情况的共同点是参与者出问题,这个时候协调者无法回滚已经提交的事务,因此严格意义上讲会出现一致性问题,然而经过询问过的事务未能提交或出问题的概率是极小的(这种说法可能不严谨),因此这我任务这是3PC和2PC的主要区别。

总结

上面已经对2PC和3PC所存在的问题进行了一定的讨论,3PC略胜与2PC。从资源角度上讲,分布式系统带来的难题是如何保证全局资源状态的一致性,上面可以看出无论是2PC还是3PC都不能绝对地解决一致性问题,甚至可以说是脆弱的,而且协议成本很高。2PC和3PC主要是在资源层面去理解和解决一致性问题,业界也有很多其他不同的思路,比如在业务服务层面(如TCC、事务消息等)、甚至是商务流程层面去解决。分布式事务问题是一个很大的课题,文中仅以个人的角度看到的问题进行理解和分析可能不够全面,如有问题,请多多包涵,同时欢迎回复消息进行讨论。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值