1.2pc
2pc(Two Phase Commitment Protocol)当一个事务操作需要跨越多个分布式节点的时候,为了保持事务处理的 ACID特性,就需要引入一个“协调者”(TM)来统一调度所有分布式节点的执行逻辑,这些被调度的分布式节点被称为 AP。TM 负责调度 AP 的行为,并最终决定这些 AP 是否要把事务真正进行提交;因为整个事务是分为两个阶段提交,所以叫 2pc
二阶段提交协议将事务提交分为两个阶段来进行处理,其执行流程过程如下:
-
阶段一:提交事务请求
- 事务询问
协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的响应 - 执行事务
各个参与者节点执行事务操作,并将 Undo 和 Redo 信息记录到事务日志中,尽量把提交过程中所有消耗时间的操作和准备都提前完成确保后面 100%成功提交事务 - 各个参与者向协调者反馈事务询问的响应
如果各个参与者成功执行了事务操作,那么就反馈给参与者yes 的响应,表示事务可以执行;如果参与者没有成功执行事务,就反馈给协调者 no 的响应,表示事务不可以执行
- 事务询问
上面这个阶段有点类似协调者组织各个参与者对一次事务操作的投票表态过程,因此 2pc 协议的第一个阶段称为“投票阶段”,即各参与者投票表明是否需要继续执行接下去的事务提交操作`
阶段二:执行事务提交
在这个阶段,协调者会根据各参与者的反馈情况来决定最终是否可以进行事务提交操作,正常情况下包含两种可能:执行事务提交、中断事务
执行事务提交
当协调者节点从所有参与者节点获得的相应消息都为”yes”响应时,那么就会执行事务提交
1. 发送提交请求
协调者节点向所有参与者节点发出commit的请求。
2.事务提交
参与者节点接收到commit请求后,会正式执行事务提交操作,并在完成提交之后释放整个事务期间内占用的资源。
3.反馈事务提交结果
参与者节点在完成事务提交之后,向协调者发送ack消息
4.完成事务
协调者节点接收到所有参与者节点反馈的ack消息后,完成事务。
中断事务
如果任一参与者节点在第一阶段返回的响应消息为NO相应,或者等待超时之后,协调者节点尚无法接收到所有参与者的反馈响应,那么就会中断事务
1.发送回滚请求
协调者节点向所有参与者节点发出rollback的请求。
2.事务回滚
参与者节点利用之前写入的Undo信息执行回滚,并释放在整个事务期间内占用的资源。
3.反馈事务回滚结果
参与者节点向协调者节点发送”回滚完成”之后,向协调者发送Ack消息
4.中断事务
协调者接收到所有参与者反馈的ack消息后,完成事务中断
2.2PC的优缺点
-
优点
:2PC的优点是很显然的,原理简单,实现方便。
目前,绝大多数关系型数据库都是采用两阶段提交协议来完成分布式事务处理的。 -
缺点
:2PC的缺点也很致命:同步阻塞,单点问题,数据不一致,太过保守
1、同步阻塞问题。
在二级段提交的执行过程中,所有参与该事务操作的逻辑的都在阻塞状态
,也就是说,各个参与者在等待其他参与者响应的过程中,将无法进行其他的任务操作
2、单点故障。
协调者的角色在整个二级段提交协议中起到了非常重要的作用
,一旦协调者出现问题,那么整个第二阶段提交流程将无法运转,更为严重的是,协调者在阶段二中出现问题的话,那么其他的参与者将会处于锁定事务资源的状态中,而无法继续完成事务操作。
3.数据不一致
在二阶段提交的阶段二中,即提交事务提交的时候,当协调者向参与者发送commit请求之后,发生了局部网络异常或者在发送commit请求过程中协调者发生了故障,这回导致只有一部分参与者接受到了commit请求。而在这部分参与者接到commit请求之后就会执行commit操作。但是其他部分未接到commit请求的机器则无法执行事务提交。于是整个分布式系统便出现了数据部一致性的现象。
4、太过保守
如果在协调者指示参与者进行事务提交询问的过程中,参与者出现故障而导致协调者始终无法获取到所有参与者的响应的消息的话,这时协调者只能依靠其自身的超时机制来判断是否中断事务,这样的策略比较保守,换句话说,二阶段提交协议没有设计相应的容错机制,当任意一个参与者节点宕机,那么协调者超时没收到响应,就会导致整个事务回滚失败。
3.3pc
3PC(three-phase commit)即三阶段提交,是2阶段提交的改进版,其将二阶段提交协议的“提交事务请求”一份为二
,形成了cancommit,precommit,do commit三个阶段
。
与两阶段提交不同的是,三阶段提交有两个改动点。
1、引入超时机制
。(超时提交策略,当第三阶段参与者等待协调者超时后会提交事务,解决参与者同步阻塞问题,同时能在发生单点故障时,继续达成一致)
2、在第一阶段和第二阶段中插入一个准备阶段
。(也是为了减少同步阻塞的发生范围
)
-
阶段一:CanCommit阶段
1.事务询问
协调者向参与者发送CanCommit请求。询问是否可以执行事务提交操作。然后开始等待参与者的响应。
2.各参与者向协调者反馈事务询问的响应
参与者接到CanCommit请求之后,正常情况下,如果其自身认为可以顺利执行事务,则返回Yes响应,并进入预备状态。否则反馈No -
阶段二:PreCommit阶段
协调者根据参与者的反应情况来决定是否可以记性事务的PreCommit操作。根据响应情况,有以下两种可能。
执行事务预提交
假如协调者从所有的参与者获得的反馈都是Yes响应,那么就会执行事务的预执行。
1.发送预提交请求
协调者向参与者发送PreCommit请求,并进入Prepared阶段。
2.事务预提交
参与者接收到PreCommit请求后,会执行事务操作,并将undo和redo信息记录到事务日志中。
3.响应反馈
如果参与者成功的执行了事务操作,则返回ACK响应,同时开始等待最终指令:提交(commit)或者中止(abort)
中断事务
假如有任何一个参与者向协调者发送了No响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
1.发送中断请求
协调者向所有参与者发送abort请求。
2.中断事务
参与者收到来自协调者的abort请求之后(或超时之后,仍未收到协调者的请求),执行事务的中断。
-
阶段三:doCommit阶段
该阶段进行真正的事务提交,也可以分为以下两种情况。
执行提交
1.发送提交请求
协调接收到参与者发送的ACK响应,那么他将从预提交状态进入到提交状态。并向所有参与者发送doCommit请求。
2.事务提交
参与者接收到doCommit请求之后,执行正式的事务提交。并在完成事务提交之后释放所有事务资源。
3.响应反馈
事务提交完之后,向协调者发送Ack响应。
4.完成事务
协调者接收到所有参与者的ack响应之后,完成事务。
中断事务
协调者没有接收到参与者发送的ACK响应(可能是接受者发送的不是ACK响应,也可能响应超时),那么就会执行中断事务。
1.发送中断请求
协调者向所有参与者发送abort请求
2.事务回滚
参与者接收到abort请求之后,利用其在阶段二记录的undo信息来执行事务的回滚操作,并在完成回滚之后释放所有的事务资源。
3.反馈结果
参与者完成事务回滚之后,向协调者发送ACK消息
4.中断事务
协调者接收到参与者反馈的ACK消息之后,执行事务的中断。
需要注意的是:
一旦进入阶段三:可能会出现:
- 协调者出现问题(单点)
- 协调者参与者之间的网络出现故障
无论出现哪种情况,最终都会导致参与者无法及时接收到来自协调者的doCommit或者是abort请求,针对这样的异常的情况,参与者都会在等待超时之后,继续进行事务提交
引入超时提交的依据:
其实这个应该是基于概率来决定的,当进入第三阶段时,参与者在第二阶段已经收到了PreCommit请求,那么协调者产生PreCommit请求的前提条件是他在第二阶段开始之前,收到所有参与者的CanCommit响应都是Yes。(一旦参与者收到了PreCommit,意味他知道大家其实都同意修改了)所以,一句话概括就是,当进入第三阶段时,由于网络超时等原因,虽然参与者没有收到commit或者abort响应,但是他有理由相信:成功提交的几率很大。
4.3pc的优缺点
三阶段提交协议的优点
: 相对于二级段提交协议,三阶段提交协议的最大的优点就是降低了参与者的阻塞的范围,并且能够在出现单点故障后继续达成一致
三阶段提交协议的缺点
: 三阶段提交协议在去除阻塞的同时也引入了新的问题,那就是参与者接收到precommit消息后,如果出现网络分区,此时协调者所在的节点和参与者无法进行正常的网络通信,在这种情况下,该参与者依然会进行事务的提交,这必然出现数据的不一致性。
网友评论