分布式事务算法
2PC (two-phase commit protocol)
2PC 就是“2 阶段提交算法”,两个阶段分别是“请求阶段”和“提交阶段”
2PC 的前提
想要实现 2PC,整个系统需要满足一定的前提条件
- 在分布式系统中,存在一个协调者和多个参与者,且互相之间可以通信
- 所有节点都采用预写式日志
- 所有节点不会永久性损坏,即使损坏,也可以恢复
第一阶段:请求阶段
- 协调者向所有参与者发送 QUERY TO COMMIT 消息,询问是否可以执行提交事务,等待响应
- 参与者这个时候要把之前已经提交的事务执行完毕、在将新请求的 Undo 信息和 Redo 信息写入日志后返回 Yes;如果这些步骤失败,返回 No
第二阶段:提交阶段
- 协调者收到所有响应都是 Yes
- 协调者向所有参与者发出 COMMIT 请求
- 参与者完成 COMMIT 请求,释放资源
- 参与者响应 ACK
- 协调者收到所有 ACK 后,完成事务
- 协调者收到一个 No
- 协调者向所有参与者发出 ROLLBACK 请求
- 参与者完成 ROLLBACK 请求,释放资源。这一步是利用了第一阶段写入的 Undo 信息
- 参与者响应 ACK
- 协调者收到所有 ACK 后,取消事务
缺点
- 同步阻塞,性能差
- 状态不一致。在消息丢失的极端情况下会出现状态不一致的问题
- 单点故障。只有一个协调者进行调度
3PC (three-phase commit protocol)
3PC 为了解决 2PC 的“单点故障”而生(在我看来,根本没解决嘛)
第一阶段:提交判断阶段
- 协调者向参与者发送 canCommit 消息,询问是否可以提交事务
- 参与者检查是否可以提交事务,返回 Yes 或 No
- 如果协调者收到 No,事务终止并通知参与者。如果全是 Yes,进入下一阶段
第二阶段:准备提交阶段
- 协调者发送 preCommit 消息给所有参与者,告诉参与者准备提交
- 参与者执行 preCommit,执行事务操作,然后将 Undo 和 Redo 记录到日志。响应 ACK
第三阶段:提交执行阶段
- 协调者收到所有 ACK 后发送 doCommit 消息,告诉参与者正式提交;否则发送回滚消息
- 参与者收到 doCommit 消息后提交事务,返回 haveCommited
- 如果参与者等待 doCommit 消息超时,会继续提交事务
缺点
除了单点故障稍稍改善了一点,另外俩毛病该有还是有
怎么改进 2PC 和 3PC?
Let’s discuss.