分布式事务一致性

二阶段提交(2 phase commit)

二阶段提交是将事务分成两个阶段进行处理,阶段一 提交事务请求,阶段二执行事务请求。
整个过程中含有两个角色协调者和参与者,协调者发起事务请求,参与者执行。
二阶段提交的核心就是对每个事务请求都采取先尝试后提交的方式。

一 提交事务请求

  • 事务询问

    协调者向所有参与者发送事务内容,询问是否可以执事务,然后等待所有参与的回应。

  • 事务执行

    参与者收到事务内容后,执行事务内容, 并将Undo和Redo的信息记入事务日志。

  • 事务询问

    若参与者成功执行了事务,就反馈给协调者Yes,如果参与者没有成功执行事务则反馈No。

    整个第一阶段得到的结果就是 事务是否可以被执行。
    Case有三种:

  • 参与者全部回复Yes
  • 存在参与者返回No
  • 存在参与者没有回应

二 执行事务请求

  • 参与者全部回复Yes, 那么久Happy的可以通知参与者执行事务了
    • 发送commit请求 到所以参与者
    • 参与者接收到commit 请求的时候,正式执行事务提交操作
    • 执行完了,发送Ack给协调者
    • 协调者收到Ack,事务结束
  • 有参与者没有回复Yes
    协调者在收到参与者返回的No或者参与者超时都没有返回时,就会直接触发事务中断的操作

    • 发送Rollback请求
    • 参与者执行Undo
    • 反馈Ack
    • 收到Ack,事务结束

二阶段提交示意图
2-phase-commit

二阶段提交是一个很简单容易理解的协议,但是也存在一些问题。

  • 在两个阶段都可能出现各种原因导致服务器之间的通讯障碍问题:

    • 第一阶段的参与者出现问题
      协调者会等待直到请求超时认为请求失败,这也会导致这次事务提交的失败。这里体现的问题就是容错性,二阶段提交没有很好的容错性机制,只能这种方式来保证。

    • 第二阶段的参与者出现问题
      事务提交的时候个别参与者没有收到commit请求,这也就意味着只有部分参与者成功执行事务。产生的问题就是各个参与者之间的数据不一致。

    • 协调者出现问题
      协调者是整个二阶段提交最重要的角色,协调者出现问题整个二阶段请求都没办法继续操作下去。特别是在阶段二出现问题的话会导致参与者处于事务锁定状态。

  • 二阶段提交的过程中,所有和此次事务相关的逻辑都处于阻塞状态,各个参与者处于相互等待状态下也无法进行其他操作。这也会带来事务处理的性能问题。

三阶段提交(3 phase commit)

三阶段请求是对二阶段提交协议的改进,将事务操作分成三个阶段

一阶段

  • Can Commit
    • 协调者发起事务询问
    • 参与者回馈是否可以执行事务内容(在二阶段提交里,参与者在接到事务内容后先尝试执行,并保存Undo和Redo)

二阶段

根据 一阶段的阶段来进行后续操作,可能为Pre commit 或 中断事务

  • Pre Commit
    • 发起预提交请求 协调者发起请求并进入prepared状态
    • 预提交事务 尝试执行事务内容,记录Undo和Redo到事务日志
    • 向协调者发送事务执行响应 同时等待协调者后续操作命令(Commit or Abort)
  • 中断事务
    有参与者一阶段返回了No或者没有响应

    • 发送Abort请求
    • 参与者中断事务 无论是收到协调者的Abort请求还是在等待协调者的过程中超时都会中断事务

三阶段

这个阶段才会真正进行事务的提交

  • Do Commit

    • 发送提交请求, 进入这个阶段,假设协调者处于正常工作状态并且接收到了所有参与者的预提交阶段的Ack消息。那么就向参与者发送 do commit请求。
    • 执行 事务提交操作,并在完成后释放事务占用资源。
    • 事务执行返程,向协调者发送Ack
    • 协调者收到Ack消息,完成事务
  • 中断事务
    协调者收到参与发送No或者在时限内没有收到所以参与者发送的反馈响应那么就中断事务

    • 发送中断请求, 向所有参与者发送Abort请求
    • 事务回滚 参与者收到Abort后,会执行事务的Undo操作,并在完成后释放事务占用资源
    • 反馈事务回滚结果 向协调者发送Ack
    • 中断事务 协调者收到所有参与者的Ack后,完成中断事务

在阶段二完成后有可能出现一下问题:

  • 协调者出现问题
  • 协调者和参与者之间通信障碍

无论是哪个问题都会导致参与者无法及时收到协调者发送的 do commit 或 abort请求。
对于这种情况在三阶段提交里,参与者会在超时后继续事务的提交。
所以有可能会出现数据不一致的情况,但是也解决了协调者单点故障的问题。

Paxos协议

Paxos是一种基于消息传递的并具有高度容错性的一致性算法。

那么Paxos到底解决了什么问题,这个问题可以用拜占庭将军作为场景描述:

拜占庭帝国

ZAB协议(Zookeeper Automic Brodcast)