08 对比两阶段提交,三阶段协议有哪些改进?


08 对比两阶段提交,三阶段协议有哪些改进?

二阶段提交协议

二阶段提交算法的成立是基于以下假设的:

  • 在该分布式系统中,存在一个节点作为协调者(Coordinator),其他节点作为参与者(Participants),且节点之间可以进行网络通信;
  • 所有节点都采用预写式日志,日志被写入后被保存在可靠的存储设备上,即使节点损坏也不会导致日志数据的丢失;
  • 所有节点不会永久性损坏,即使损坏后仍然可以恢复。

两阶段提交中的两个阶段,指的是 Commit-request 阶段Commit 阶段,两阶段提交的流程如下:

在这里插入图片描述

提交请求阶段

  1. 事务询问
    协调者向所有的参与者发送事务内容,询问是否可以执行事务提交的操作,并开始等待各个参与者的响应。
  2. 执行事务
    各个参与者结点执行事务操作,并将 undo 和 Redo 信息记入事务日志中。
  3. 各参与者向协调者反馈事务询的响应

提交阶段

协调者会根据各个参与者的反馈情况来决定最终是否可以进行事务提交操作,包含以下两种可能:

第一种可能:假如协调者从所有的参与者获得的反馈都是 yes 响应,那么就会执行事务提交

  1. 发送提交请求
    协调者向所有参与者结点发出 Commit 请求。
  2. 事务提交
    参与者接受到 Commit 请求后,会正式执行事务提交操作,并在完成提交之后释放整个事务执行期间占用的事务资源。
  3. 反馈事务提交结果
    参与者在完成事务提交之后,向协调者发送 ack 消息。
  4. 完成事务
    协调者接收到所有参与者反馈的 ack 信息后,完成事务。

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

  1. 发送回滚请求
    协调者向所有参与结点发出 RollBack 请求。
  2. 事务回滚
    参与者接受到 RollBack 请求后,会利用其在阶段一种记录的 Undo 信息来执行事务回滚操作,并在完成回滚之后释放在整个事务执行期间占用的资源。
  3. 反馈事务回滚结果
    参与者在完成事务回滚之后,向协调者发送 ack 消息。
  4. 中断事务
    协调者接收到所有参与者反馈的 ack 消息后,完成事务中断。

两阶段提交存在的问题

  • 资源被同步阻塞

在执行过程中,所有参与节点都是事务独占状态,当参与者占有公共资源时,那么第三方节点访问公共资源会被阻塞。

  • 协调者可能出现单点故障

一旦协调者发生故障,参与者会一直阻塞下去。

  • 在 Commit 阶段出现数据不一致

在第二阶段中,假设协调者发出了事务 Commit 的通知,但是由于网络问题该通知仅被一部分参与者所收到并执行 Commit,其余的参与者没有收到通知,一直处于阻塞状态,那么,这段时间就产生了数据的不一致性。

三阶段提交协议

为了解决二阶段协议中的同步阻塞等问题,三阶段提交协议在协调者和参与者中都引入了超时机制,并且把两阶段提交协议的第一个阶段拆分成了两步:询问,然后再锁资源,最后真正提交。

三阶段中的 Three Phase 分别为 CanCommit、PreCommit、DoCommit 阶段

在这里插入图片描述

CanCommit 阶段

  1. 事务询问
    协调者向所有的参与者发送一个包含事务内容的 CanCommit 请求,询问是否可以执行事务提交操作,并开始等待参与者的响应。
  2. 各参与者向协调者反馈事务询问的响应
    参与者在接收到来自协调者的 CanCommit 请求后,正常情况下,如果其认为可以顺利执行事务,那么会反馈 Yes 响应,并进入预备状态,否则反馈 No 响应。

PreCommit 阶段

协调者根据参与者的反应情况来决定是否可以继续事务的 PreCommit 操作。根据响应情况,有以下两种可能。

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

  • 发送预提交请求,协调者向参与者发送 PreCommit 请求,并进入 Prepared 阶段;
  • 事务预提交,参与者接收到 PreCommit 请求后,会执行事务操作;
  • 响应反馈,如果参与者成功执行了事务操作,则返回 ack 响应,同时开始等待最终指令。

B. 假如有任何一个参与者向协调者发送了 No 响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就中断事务:

  • 发送中断请求,协调者向所有参与者发送 abort 请求;
  • 中断事务,参与者收到来自协调者的 abort 请求之后,执行事务的中断。

DoCommit 阶段

该阶段进行真正的事务提交,也可以分为以下两种情况。

A. 执行提交

  • 发送提交请求。协调者接收到参与者发送的 ack 响应后,那么它将从预提交状态进入到提交状态,并向所有参与者发送 DoCommit 请求。
  • 事务提交。参与者接收到 DoCommit 请求之后,执行正式的事务提交,并在完成事务提交之后释放所有事务资源。
  • 响应反馈。事务提交完之后,向协调者发送 ack 响应。
  • 完成事务。协调者接收到所有参与者的 ack 响应之后,完成事务。

B. 中断事务
进入这一阶段,假设协调者处于正常工作状态,并且有任意一个参与者向协调者反馈了 No 响应,或者在等待超时后,协调者尚无法接受到所有参与者的反馈响应,那么就会中断事务。

  1. 发送中断请求
    协调者向所有参与者结点发送 abort 请求。
  2. 事务回滚
    参与者接收到 abort 请求后,会利用其在阶段二中记录的 Undo 信息来执行事务回滚操作,并在完成回滚后释放整个事务执行期间占用的资源。
  3. 反馈事务回滚结果
    参与者在完成事务回滚会后,向协调者发送 ack 消息。
  4. 中断事务
    协调者接收到所有参与者反馈的 ack 消息后,中断事务。

三阶段提交做了哪些改进

引入超时机制

在 2PC 中,只有协调者拥有超时机制,如果在一定时间内没有收到参与者的消息则默认失败,3PC 同时在协调者和参与者中都引入超时机制。

添加预提交阶段

在 2PC 的准备阶段和提交阶段之间,插入一个准备阶段,使 3PC 拥有 CanCommit、PreCommit、DoCommit 三个阶段,PreCommit 是一个缓冲,保证了在最后提交阶段之前各参与节点的状态是一致的。

三阶段提交协议存在的问题

三阶段提交协议同样存在问题,具体表现为,在阶段三中,如果参与者接收到了 PreCommit 消息后,出现了不能与协调者正常通信的问题,在这种情况下,参与者依然会进行事务的提交,这就出现了数据的不一致性。

两阶段和三阶段提交的应用

两阶段提交是一种比较精简的一致性算法/协议,很多关系型数据库都是采用两阶段提交协议来完成分布式事务处理的,典型的比如 MySQL 的 XA 规范。

在事务处理、数据库和计算机网络中,两阶段提交协议提供了分布式设计中的数据一致性的保障,整个事务的参与者要么一致性全部提交成功,要么全部回滚。MySQL Cluster 内部数据的同步就是用的 2PC 协议。

MySQL 的主从复制

在 MySQL 中,二进制日志是 server 层,主要用来做主从复制即时点恢复时使用的;而事务日志(redo Log)是 InnoDB 存储引擎层,用来保证事务安全的。

在数据库运行中,需要保证 binlog 和 redo log 的一致性,如果顺序不一致, 则意味着 Master-Slave 可能不一致。

在开启 binlog 后,如何保证 binlog 和 redo log 的一致性呢?MySQL 使用的就是二阶段提交,内部会自动将普通事务当做一个 XA 事务(内部分布式事务)来处理:

  • Commit 会被自动的分成 Prepare 和 Commit 两个阶段;
  • Binlog 会被当做事务协调者(Transaction Coordinator),Binlog Event 会被当做协调者日志。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

久违の欢喜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值