分布式协同 - 分布式事务_2PC 3PC解决方案
文章目录
- 导图
- Pre
- 2PC(Two-Phase Commit)协议
- 准备阶段
- 提交阶段
- 情况 1:只要有一个事务参与者反馈未就绪(no ready),事务协调者就会回滚事务
- 情况 2:当所有事务参与者均反馈就绪(ready)消息时,事务协调者会提交(commit)事务
- 3PC(Three-Phase Commit)协议
- 3PC的三个阶段
- 3PC 的流程
- 3PC 和 2PC 的主要区别
- 1. 阶段数量不同
- 2. 容错能力
- 3. 协议的安全性与复杂性
- 4. 阻塞问题
- 5. 事务资源锁定
- 6. 性能开销
- 总结
导图
Pre
分布式协同 - 分布式事务一二事儿DTP 定义了分布式事务的处理模型,可以针对这个模型提出分布式事务的解决方案,2PC 就是其中一种。
2PC 的全称为两阶段提交(Two Phase Commitment Protocol),是 DTP 模型的最佳实践,解决了在分布式服务或数据库场景下,同一事务对多个节点进行操作的数据一致性问题。
2PC 在一定程度上遵守 ACID 理论的刚性事务的要求,保证了强一致性。 2PC 中有两个概念,
- 一个是事务协调者,对应 DTP 模型中的事务管理器,用来协调事务,所有事务什么时候准备好、什么时候可以提交都由它来协调和管理;
- 另一个是事务参与者,对应 DTP 模型中的资源管理器,主要负责处理具体事务、管理需要处理的资源。例如事务参与者可以处理订票业务,扣款业务。
2PC(Two-Phase Commit)协议
+-----------------+ +------------------+ +-----------------+
| Transaction | | Coordinator | | Participant |
| Client | | Node | | Node |
+-----------------+ +------------------+ +-----------------+
| | |
|----------(1) Request Start ------> |
| | |
| | --------------(2) Prepare-------->|
| | |
| | <--------- (3) Acknowledge ------|
| | |
| | |
| | --------------(4) Commit--------->|
| | |
| | <--------- (5) Acknowledge ------|
| | |
| | |
| (End) (End)
准备阶段
第一阶段(准备阶段):如下图 所示
事务协调者(事务管理器)给每个事务参与者(资源管理器)发送准备(prepare)消息,目的是询问大家是不是都准备好了,马上就要执行事务了。事务参与者会根据自身业务和资源情况进行检查,然后给出反馈。检查过程根据业务内容的不同而不同,例如订票业务需要检查是否有剩余票、扣款业务需要检查余额是否足够。
只有检查通过,才能返回就绪(ready)信息。否则,事务将终止,并且等待下次询问。由于检查过程需要完成一些操作,因此需要写 redo 日志和 undo 日志,以便事务失败重试,或者失败回滚时使用。
提交阶段
第二阶段(提交阶段):如下图所示
如果事务协调者接收到事务参与者检查失败或者超时的消息,会给其发送回滚(rollback)消息,否则发送提交(commit)消息。
情况 1:只要有一个事务参与者反馈未就绪(no ready),事务协调者就会回滚事务
- a) 事务协调者向所有事务参与者发出回滚请求。
- b) 事务参与者使用第一阶段中 undo 日志里的信息执行回滚操作,并且释放整个事务期间占用的资源。
- c) 各事务参与者向事务协调者反馈应答(ack)消息,表示完成操作。
- d) 事务协调者接收到所有事务参与者反馈的应答消息,即完成了事务回滚。
情况 2:当所有事务参与者均反馈就绪(ready)消息时,事务协调者会提交(commit)事务
- a) 事务协调者向所有事务参与者发出正式提交事务的请求。
- b) 事务参与者执行提交(commit)操作,并释放整个事务期间占用的资源。
- c) 各事务参与者向事务协调者反馈应答(ack)消息,表示完成操作。
- d) 事务协调者接收到所有事务参与者反馈的应答(ack)消息,即完成了事务提交。
3PC(Three-Phase Commit)协议
3PC(三阶段提交)是分布式事务中的一种协议,旨在解决2PC协议中的阻塞问题。3PC协议通过在2PC的基础上增加了一个阶段,增加了事务的容错能力,从而避免了协调者或参与者崩溃时可能发生的阻塞现象。
3PC的三个阶段
-
CanCommit 阶段(询问阶段)
- 协调者向所有参与者发送“CanCommit”请求,询问它们是否可以提交事务。
- 参与者收到请求后,会检查本地的事务状态。如果没有冲突,且可以提交,它们就返回“Ready”响应;如果事务存在问题,则返回“No”响应,表示无法提交。
-
PreCommit 阶段(预提交阶段)
- 如果所有参与者都返回了“Ready”,协调者就会向所有参与者发送“PreCommit”命令,表示准备提交事务,并让它们锁定相关资源。
- 参与者在接收到“PreCommit”命令后,执行事务的预提交操作并返回确认。
-
DoCommit 阶段(提交阶段)
- 如果所有参与者都返回了预提交确认(“PreCommit”),协调者会向所有参与者发送“DoCommit”命令,正式提交事务。
- 参与者接收到“DoCommit”命令后,执行提交操作,事务完成。
3PC 的流程
+-----------------+ +------------------+ +-----------------+
| Transaction | | Coordinator | | Participant |
| Client | | Node | | Node |
+-----------------+ +------------------+ +-----------------+
| | |
|----------(1) Request Start ------> |
| | |
| | --------(2) CanCommit --------->|
| | |
| | <----------(3) Ready/No --------|
| | |
| | --------(4) PreCommit --------->|
| | |
| | <----------(5) PreCommitAck -----|
| | |
| | --------(6) DoCommit ---------->|
| | |
| | <----------(7) DoCommitAck ------|
| | |
| (End) (End)
3PC 和 2PC 的主要区别
1. 阶段数量不同
-
2PC 有两个阶段:
- Prepare: 协调者询问参与者是否能提交事务。
- Commit/Abort: 根据参与者的响应,协调者决定是否提交或回滚事务。
-
3PC 有三个阶段:
- CanCommit: 协调者询问参与者是否准备提交。
- PreCommit: 协调者发送预提交命令,参与者准备提交并锁定资源。
- DoCommit: 协调者发送最终提交命令,事务正式提交。
2. 容错能力
- 2PC 在协调者或参与者崩溃时可能会出现阻塞。例如,如果协调者崩溃后,参与者不知道是应该提交还是回滚,系统可能会陷入阻塞状态,无法继续执行。
- 3PC 增加了一个额外的阶段(PreCommit),并且在每个阶段都有明确的响应协议,可以减少系统在协调者或参与者崩溃时的阻塞风险。3PC通过引入超时机制和预提交锁定,有效减少了数据不一致和系统停滞的概率。
3. 协议的安全性与复杂性
- 2PC 协议相对简单,但存在阻塞问题,且在部分情况下(例如,协调者崩溃),事务无法保证最终一致性。
- 3PC 协议在设计上更加复杂,通过引入预提交阶段,提高了系统的容错能力,但也增加了协议的开销和实现的复杂性。
4. 阻塞问题
- 2PC 存在阻塞问题,特别是在协调者或参与者崩溃的情况下,事务无法继续或回滚,可能会导致长时间的停滞。
- 3PC 通过引入额外的阶段,并要求所有参与者在每个阶段都给予明确的响应,避免了阻塞的可能性。当协调者或参与者崩溃时,系统会通过超时机制自动恢复,减少了长时间的停滞。
5. 事务资源锁定
- 2PC 中,事务资源在提交后才被释放,可能会因为参与者的延迟或崩溃导致长时间的资源占用。
- 3PC 引入了预提交阶段,在PreCommit时就锁定了资源并确保它们在提交前是有效的,因此能更有效地管理资源的占用。
6. 性能开销
- 2PC 因为只有两个阶段,协议简单,性能相对较好,但当系统出现故障时,性能和一致性会受到较大影响。
- 3PC 虽然增加了一个阶段,但引入了更多的容错机制,可能会有稍微的性能开销,但能在故障恢复时保持更高的可用性。
总结
特性 | 2PC (Two-Phase Commit) | 3PC (Three-Phase Commit) |
---|---|---|
阶段数量 | 2个阶段:Prepare(准备阶段)和Commit/Abort(提交/回滚阶段) | 3个阶段:CanCommit(询问阶段)、PreCommit(预提交阶段)、DoCommit(提交阶段) |
协议设计 | 基于两阶段协议,协议简单但容易导致阻塞问题 | 基于三阶段协议,增加了预提交阶段,减少了阻塞问题 |
阻塞问题 | 存在阻塞问题,特别是当协调者或参与者崩溃时,系统可能无法继续 | 通过引入PreCommit阶段,减少了崩溃时的阻塞问题,避免了长时间停滞 |
协调者崩溃的处理 | 协调者崩溃后,参与者不确定事务是提交还是回滚,导致阻塞 | 由于引入了CanCommit和PreCommit阶段,协调者崩溃后的恢复能力较强,减少了阻塞的可能 |
参与者崩溃的处理 | 如果参与者在Prepare阶段崩溃,事务可能无法提交 | 在PreCommit阶段,参与者能锁定资源,如果崩溃,系统能更好恢复,减少了不一致情况 |
事务提交的一致性 | 保证一致性,但有可能因为协调者或参与者崩溃导致无法提交或回滚 | 在多数情况下保证一致性,并且通过额外阶段减少了崩溃带来的影响 |
资源管理 | 资源管理依赖于Prepare阶段,协调者发出提交或回滚命令 | 资源管理通过PreCommit阶段锁定资源,协调者发送最终提交命令 |
性能开销 | 由于只有两个阶段,性能较高,但可能因为故障导致较长的延迟 | 增加了一个阶段,性能会有一定的开销,但能有效减少阻塞问题 |
协议复杂性 | 协议较简单,实现起来相对容易,但缺乏容错能力 | 协议更复杂,要求在协议层面上有更多的容错设计和实现 |
适用场景 | 适用于对一致性要求较高的场景,如分布式数据库事务 | 适用于对高可用性和容错性要求较高的场景,尤其是需要更好恢复能力的分布式系统 |
超时处理 | 通常需要外部机制(如超时检测)来处理超时问题 | 协议本身提供了对超时和崩溃的处理机制,有更强的容错能力 |
- 2PC 由于其简单的设计,适用于一些不涉及复杂容错的场景,但它容易因为崩溃或故障导致阻塞问题,事务可能无法继续进行。
- 3PC 在 2PC 的基础上增加了一个阶段,提升了系统容错能力,减少了由于协调者或参与者崩溃导致的阻塞,但相应地增加了协议的复杂度和性能开销。
在选择2PC还是3PC时,需要根据具体应用场景的容错要求、性能需求以及系统复杂度进行权衡。