分布式学习手记02 - 一致性协议:二、三阶段提交
分布式事务跨越多个节点,为保持事务处理的 ACID 特性,需要一个“协调者”(Coordinator)组件来统一调度所有分布式节点——“参与者”(Participant)的执行逻辑。
协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务真正进行提交。
两阶段提交 2PC
2PC - 2 Phase Commit 为了使所有分布式节点在事务处理过程中,保持原子性和一致性而设计的算法。
Phase 1 投票
第一阶段:提交事务请求
-
事务询问 ->
协调者向所有参与者发送事务内容,询问是否可以执行事务提交操作,并等待参与者响应;
-
执行事务 ->
各参与者执行事务,并将 Undo 信息和 Redo 信息写入日志(此处 Redo 的参与者已完成事务执行);
-
参与者响应协调者事务执行询问 ->
Redo 的参与者向协调者发送 Yes 响应,表是事务可以执行,Undo 的参与者发送 No 响应,表示事务无法执行;
Phase 2 执行
第二阶段:执行事务提交
协调者会根据参与者反馈决定是否进行事务提交操作(收到 No 响应或等待超时,则向参与者发送回滚消息,否则提交消息),并释放事务处理过程中使用的锁资源。
所以该阶段包含两种可能:
a- 参与者反馈都是 Yes 响应,执行事务提交:
-
发送请求提交 ->
上阶段最后一步协调者收到 Yes 响应,于是向参与者发出 Commit 请求;
-
事务提交 ->
参与者收到 Commit 请求,正式执行事务提交操作,完成后释放执行事务期间站占用的资源;
-
反馈事务提交结果 ->
参与者完成事务提交后,向协调者发送 ACK 消息;
-
完成事务 -|
协调者收到所有参与者的 ACK 消息后,完成事务。
b- 若有参与者反馈 No 响应,或协调者等待响应超时,中断事务:
-
发送回滚请求 ->
上阶段最后一步协调者收到 No 响应,则向参与者发出 Rollback 请求;
-
事务回滚 ->
参与者收到 Rollback 请求后,利用上阶段的 Undo 信息执行事务回滚操作,并在完成后释放执行事务期间占用的资源;
-
反馈事务回滚结果 ->
参与者完成事务回滚后,向协调者发送 ACK 消息;
-
中断事务 -|
协调者收到所有参与者的 ACK 消息后,完成事务中断。
缺点
-
同步阻塞
响应过程中,参与者阻塞等待,极大限制系统性能
-
单点问题
协调者若发生故障后果严重
-
数据不一致
第二阶段,若部分参与者没收到 Commit 消息,则与收到 Commit 消息的参与者事务操作产生差异,系统数据不再一致
-
保守
失败或超时,没有较为完善的容错机制
三阶段提交
3PC - 3 Phase Commit 两阶段提交的改进版,优化二阶段提交中参与者和协调者都挂掉的情况
Phase 1 CanCommit
-
事务询问 ->
协调者向参与者发送包含事务内容的 CanCommit 请求,等待响应;
-
参与者响应 ->
参与者收到 CanCommit 请求后,评估是否能执行事务,根据评估结果反馈 Yes / No 响应;
Phase 2 PreCommit
预提交阶段,协调者根据参与者反馈决定是否进行事务 PreCommit 操作,因此有两种情况:
a- 协调者收到全是 Yes 反馈,执行事务预提交
-
发送预提交请求 ->
协调者向参与者发送 PreCommit 请求,进入 Prepared 状态;
-
事务预提交 ->
参与者收到 PreCommit 请求后,执行事务操作,并根据执行结果,记录 Undo / Redo 信息;
-
参与者反馈事务执行响应 ->
若参与者成功执行事务,给协调者发送 ACK 响应,等待最终指令(提交或终止);
b- 协调者收到部分 No 反馈,或等待超时,中断事务
-
发送中断请求 ->
协调者向参与者发送 Abort 请求;
-
中断事务 -|
参与者收到 Abort 请求,或等待超时,则中断事务。
Phase 3 DoCommit
本阶段进行真正的事务提交,根据预提交阶段参与者事务执行的反馈结果,存在两种可能:
a- 执行提交
-
发送提交请求 ->
协调者收到参与者执行成功呃 ACK 响应,则从“预提交”状态切换到“提交”状态,并向所有参与者发送 DoCommit 请求;
-
事务提交 ->
参与者收到 DoCommit 请求后,正式执行事务提交操作,完成后释放事务执行期间占用的资源;
-
反馈事务提交结果 ->
参与者完成事务提交后,向协调者发送 ACK 消息;
-
完成事务 -|
协调者接收到所有参与者的 ACK 消息后,完成事务。
b- 中断事务
预提交阶段,协调者若收到参与者 PreCommit 操作失败反馈或等待超时,则中断事务
-
发送中断请求 ->
协调者向参与者发送 Abort 请求;
-
事务回滚 ->
参与者收到 Abort 请求后,会利用 Undo 信息执行事务回滚操作,完成后释放占用资源;
-
反馈事务回滚结果 ->
参与者完成事务回滚后,向协调者发送 ACK 消息;
-
中断事务 -|
协调者接收到所有参与者的 ACK 消息后,中断事务。
优缺点
-
3PC 相对 2PC 优点在于第一阶段降低参与者的阻塞,并弥补 2PC 参与者和协调者都挂掉带来的数据不一致问题。
-
3PC 在 DoCommit 阶段也会有数据不一致的风险,具体可以参考 深入理解分布式系统的2PC和3PC 这篇文章。