分布式事务综述 (5)

当一个事务跨多个节点时,为了保持事务的原子性与一致性,而引入一个协调者来统一掌控所有参与者的操作结果,并指示它们是否要把操作结果进行真正的提交或者回滚(rollback)。

二阶段提交的算法思路可以概括为:参与者将操作成败通知协调者,再由协调者根据所有参与者的反馈情报决定各参与者是否要提交操作还是中止操作。

核心思想就是对每一个事务都采用先尝试后提交的处理方式,处理后所有的读操作都要能获得最新的数据,因此也可以将二阶段提交看作是一个强一致性算法

处理流程

简单一点理解,可以把协调者节点比喻为带头大哥,参与者理解比喻为跟班小弟,带头大哥统一协调跟班小弟的任务执行。

阶段 1:准备阶段

准备阶段有如下三个步骤:

协调者向所有参与者发送事务内容,询问是否可以提交事务,并等待所有参与者答复。

各参与者执行事务操作,将 undo 和 redo 信息记入事务日志中(但不提交事务)。

如参与者执行成功,给协调者反馈 yes,即可以提交;如执行失败,给协调者反馈 no,即不可提交。

阶段 2:提交阶段

如果协调者收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(rollback)消息;否则,发送提交(commit)消息。

参与者根据协调者的指令执行提交或者回滚操作,释放所有事务处理过程中使用的锁资源。(注意:必须在最后阶段释放锁资源) 接下来分两种情况分别讨论提交阶段的过程。

图 9

情况 1,当所有参与者均反馈 yes,提交事务,如上图:

协调者向所有参与者发出正式提交事务的请求(即 commit 请求)。

参与者执行 commit 请求,并释放整个事务期间占用的资源。

各参与者向协调者反馈 ack(应答)完成的消息。

协调者收到所有参与者反馈的 ack 消息后,即完成事务提交。

图 10

情况 2,当任何阶段 1 一个参与者反馈 no,中断事务,如上图:

协调者向所有参与者发出回滚请求(即 rollback 请求)。

参与者使用阶段 1 中的 undo 信息执行回滚操作,并释放整个事务期间占用的资源。

各参与者向协调者反馈 ack 完成的消息。

协调者收到所有参与者反馈的 ack 消息后,即完成事务中断。

方案总结

2PC 方案实现起来简单,实际项目中使用比较少,主要因为以下问题:

性能问题:所有参与者在事务提交阶段处于同步阻塞状态,占用系统资源,容易导致性能瓶颈。

可靠性问题:如果协调者存在单点故障问题,如果协调者出现故障,参与者将一直处于锁定状态。

数据一致性问题:在阶段 2 中,如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,那么就导致了节点之间数据的不一致。

3PC(三阶段提交)方案 方案简介

三阶段提交协议,是二阶段提交协议的改进版本,与二阶段提交不同的是,引入超时机制。同时在协调者和参与者中都引入超时机制。

三阶段提交将二阶段的准备阶段拆分为 2 个阶段,插入了一个 preCommit 阶段,使得原先在二阶段提交中,参与者在准备之后,由于协调者发生崩溃或错误,而导致参与者处于无法知晓是否提交或者中止的“不确定状态”所产生的可能相当长的延时的问题得以解决。

处理流程

阶段 1:canCommit

协调者向参与者发送 commit 请求,参与者如果可以提交就返回 yes 响应(参与者不执行事务操作),否则返回 no 响应:

协调者向所有参与者发出包含事务内容的 canCommit 请求,询问是否可以提交事务,并等待所有参与者答复。

参与者收到 canCommit 请求后,如果认为可以执行事务操作,则反馈 yes 并进入预备状态,否则反馈 no。

阶段 2:preCommit

协调者根据阶段 1 canCommit 参与者的反应情况来决定是否可以进行基于事务的 preCommit 操作。根据响应情况,有以下两种可能。

图 11

情况 1:阶段 1 所有参与者均反馈 yes,参与者预执行事务,如上图:

协调者向所有参与者发出 preCommit 请求,进入准备阶段。

参与者收到 preCommit 请求后,执行事务操作,将 undo 和 redo 信息记入事务日志中(但不提交事务)。

各参与者向协调者反馈 ack 响应或 no 响应,并等待最终指令。

图 12

情况 2:阶段 1 任何一个参与者反馈 no,或者等待超时后协调者尚无法收到所有参与者的反馈,即中断事务,如上图:

协调者向所有参与者发出 abort 请求。

无论收到协调者发出的 abort 请求,或者在等待协调者请求过程中出现超时,参与者均会中断事务。

阶段 3:do Commit

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

图 13

图 14

情况 1:阶段 2 所有参与者均反馈 ack 响应,执行真正的事务提交,如上图:

如果协调者处于工作状态,则向所有参与者发出 do Commit 请求。

参与者收到 do Commit 请求后,会正式执行事务提交,并释放整个事务期间占用的资源。

各参与者向协调者反馈 ack 完成的消息。

协调者收到所有参与者反馈的 ack 消息后,即完成事务提交。

图 15

图 16

情况 2:阶段 2 任何一个参与者反馈 no,或者等待超时后协调者尚无法收到所有参与者的反馈,即中断事务,如上图:

如果协调者处于工作状态,向所有参与者发出 abort 请求。

参与者使用阶段 1 中的 undo 信息执行回滚操作,并释放整个事务期间占用的资源。

各参与者向协调者反馈 ack 完成的消息。

协调者收到所有参与者反馈的 ack 消息后,即完成事务中断。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywjfp.html