浅谈分布式事务及解决方案( 二 )

  • 如果所有的参与者都向协调者做了 “Vote Commit” 的反馈的话,那么流程进入第二个阶段 。
  • 3.1.2 提交阶段(commit phase)
    浅谈分布式事务及解决方案

    文章插图
    1)如果所有参与者均反馈的是成功,协调者就会向所有参与者发送 “全局提交确认通知(global_commit)”,参与者 Participant 就会完成自身本地数据库事务的提交,并将提交结果回复 “ack” 消息给协调者 Coordinator,然后协调者 Coordinator 就会向调用方返回分布式事务处理完成的结果 。如果有任何一个参与者返回失败,则回滚事务 。
    浅谈分布式事务及解决方案

    文章插图
    2)如果参与者向协调者反馈 “Vote_Abort” 消息,即返回了失败的消息 。此时分布式事务协调者 Coordinator 就会向所有的参与者 Participant 发起事务回滚的消息(“global_rollback”),此时各个参与者就会回滚本地事务,释放资源,并且向协调者发送 “ack” 确认消息,协调者就会向调用方返回分布式事务处理失败的结果 。
    浅谈分布式事务及解决方案

    文章插图
    以上就是两阶段提交的基本过程了,那么按照这个两阶段提交协议 , 分布式系统的数据一致性问题就能解决么?
    3.2 2PC 存在的问题
    其实 , 2PC 只是通过增加了事务协调者(Coordinator)的角色来通过 2 个阶段的处理流程来解决分布式系统中一个事务需要跨多个服务的数据一致性问题 。
    以下几点是 XA - 两阶段提交协议中会遇到的一些问题:
    • 性能问题:2PC 中的所有的参与者节点都为事务阻塞型,当某一个参与者节点出现通信超时,其余参与者都会被动阻塞占用资源不能释放 。
    • 协调者单点故障问题:由于严重的依赖协调者,一旦协调者发生故障,而此时参与者还都处于锁定资源的状态 , 无法完成事务 commit 操作 。虽然协调者出现故障后 , 会重新选举一个协调者 , 可无法解决因前一个协调者宕机导致的参与者处于阻塞状态的问题 。
    • 网络闪断导致脑裂:第二阶段中协调者向参与者发送 commit 命令之后 , 一旦此时发生网络抖动 , 导致一部分参与者接收到了 commit 请求并执行,可其他未接到 commit 请求的参与者无法执行事务提交 。进而导致整个分布式系统出现了数据不一致 。
    4 三阶段提交(3PC)三阶段提交又称 3PC,在 2PC 的基础上增加了 CanCommit 阶段,并引入了超时机制 。一旦事务参与者迟迟没有收到协调者的 Commit 请求,就会自动进行本地 commit,这样相对有效地解决了协调者单点故障的问题 。
    4.1 3PC 运行原理
    4.1.1 CanCommit 阶段
    1. 协调者向参与者发出 CanCommit  , 进行事务询问操作,所有参与者都反馈 yes 后,才能进入下一个阶段 。(这一个阶段时不锁表 , 不像 2pc 第一个阶段就开始锁表,3pc 的阶段一是为了先排除个别参与者不具备提交事务能力的前提下,而避免锁表 。)简单来说就是检查下自身状态的健康性 。
    2. 有任何一个参与者反馈的结果是 No,整个分布式事务就会中断 , 协调者就会向所有的参与者发送 “abort” 请求 。
    4.1.2 PreCommit 阶段
    1. 在阶段一中,如果所有的参与者都返回 Yes 的话,那么就会进入 PreCommit 阶段进行事务预提交 。此时分布式事务协调者会向所有的参与者发送 PreCommit 请求,参与者收到后开始执行事务操作 , 并将 Undo 和 Redo 信息记录到事务日志中 。参与者执行完事务操作后(此时属于未提交事务的状态) , 就会向协调者反馈 “Ack” 表示已经准备好提交,并等待协调者的下一步指令 。
    2. 有任何一个参与者反馈的结果是 No,或协调者在等待参与者节点反馈的过程中超时(2PC 中只有协调者可以超时,参与者没有超时机制) 。整个分布式事务就会中断 , 协调者就会向所有的参与者发送 “abort” 请求 。
    4.1.3 DoCommit 阶段
    1. 在阶段二中如果所有的参与者都可以进行 PreCommit 提交 , 那么协调者就会从 “预提交状态”->“提交状态” 。然后向所有的参与者发送”doCommit” 请求,参与者在收到提交请求后,执行事务提交操作,并向协调者反馈 “Ack” 消息 , 协调者收到所有参与者的 Ack 消息后完成事务 。


      推荐阅读