2PC 3PC
2.1 2PC 和 3PC
分布式系统中,节点只知道自己的实务操作的成与败,无法获取其他节点的操作结果。因此,跨多节点事务,需要引入一个“协调者”保证ACID特性。协调者负责调度参与者的行为,并最终决定参与者是否真正提交事务。基于此思想,衍生出二阶段提交和三阶段提交两种协议。
2.1.1 2PC Two-Phase Commit
事务提交过程分两个阶段进行处理:
阶段一:提交事务请求
- 事务询问
协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待各参与者的相应。 - 执行事务
参与者执行实务操作,将Undo和Redo信息记入事务日志。 - 参与者向协调者反馈事务询问的相应
如果参与者成功执行了实务操作,那么久反馈给协调者yes,表示事务可以执行;反之,这反馈no;
- 事务询问
上述内容形式上类似是,协调者组织参与者对一次事务操作投票表态的过程,因此成为“投票阶段”,即各个参与者标明是否继续执行接下去的事务提交操作。
阶段二:执行事务提交
协调者收集投票结果决定是否进行事务提交操作,包含两种可能
-
- 执行事务提交(投票都为yes)
1.向参与者发送提交请求
2.参与者收到提交请求,执行提交,释放事务占用的资源
3.参与者反馈提交结果,发送Ack消息
4.协调者收到所有参与者Ack,完成事务 - 中断事务(存在反馈no,或者超时无反馈)
1.协调者向所有参与者发送Rollback请求
2.执行回滚,参与者收到Rollback请求,利用Undo信息执行回滚,释放事务占用的资源
3.反馈结果,参与者反馈回滚结果,发送Ack
4.中断事务,协调者收到所有Ack消息后,完成事务中断。
- 执行事务提交(投票都为yes)
事务处理分为两个阶段:投票,执行。(先尝试后提交的处理方式)
优缺点
优点:原理简单,实现方便
缺点:同步阻塞,单点问题,脑裂,太保守
同步阻塞:二阶段提交执行过程中,所有参与事务操作的逻辑都处于阻塞状态
单点问题:协调者单点,出现问题无法运转,甚至二阶段协调者出现问题参与者会锁定事务资源
数据不一致:部分参与者没有收到Commit请求没有提交,部分收到而提交,则出现这个系统数据不一致
太过保守:二阶段提交协议没有涉及较完善的容错机制,任意一个节点失败都会导致整个事务失败
2.1.2 3PC
阶段一:CanCommit
- 事务询问
- 参与者反馈询问响应
阶段二:PreCommit
此阶段,协调者根据参与者的反馈情况决定是否进行事务的PreCommit操作,存在两种可能:
- 执行事务预提交(参与者反馈都是Yes)
a 向参与者发送preCommit请求,并进入Prepared阶段
b 参与者收到preCommit请求,执行实务操作,将Undo和Redo信息记录到事务日志中
c 参与者反馈事务执行响应,后等待最终的提交或终止指令 - 中断事务(任何参与者反馈no)
a 向参与者发送中断abort请求
b 参与者收到abort请求,或等待超时,参与者中断事务
- 执行事务预提交(参与者反馈都是Yes)
阶段三:doCommit
- 执行提交
a 发送提交请求,
b 参与者收到doCommit请求,正式执行事务提交操作,完成提交之后释放事务占用的资源
c 反馈事务提交结果
d 协调者收到所有Ack 完成事务 - 中断事务(参与者存在no反馈或协调者等待所以反馈超时)
a 向所有参与者发送abort请求
b 参与者收到abort,利用Undo信息回滚,释放事务占用的资源
c 相协调者发送Ack 消息
d 协调者收到所有参与者反馈的Ack消息后,中断事务
- 执行提交
注意:一旦进入阶段三,可能出现两种故障。
-
- 协调者出现问题
- 协调者和参与者间网络故障
无论出现哪种情况,最终导致参与者无法及时接收到协调者的doCommit或是abort请求,针对这种异常,参与者都会超时之后,继续提交事务
优点:相较于二阶段提交协议,降低了参与者的阻塞范围,并能够在出现单点故障后继续搭乘一致
缺点:引入新的问题,参与者收到preCommit后,如果出现网络分区,此时协调者所在节点和参与者无法进行正常网络通信,这种情况下,参与者已让会提交事务,这必然会出现不一致性。