一致性协议

分布式系统在设计的过程中,往往会在系统的可用性和数据一致性之间进行反复的权衡,于是产生了一系列的一致性协议。

2PC与3PC

通常需要引入“协调者(Coordinator)”的组件来统一调度所有分布式节点上的执行逻辑,这些被调度的分布式节点则被称为“参与者(Participant)”。协调者负责调度参与者的行为,并最终决定这些参与者是否要把事务真正进行提交。基于这个思想,衍生出了两阶段提交和三阶段提交两种协议。

2PC

  • 阶段一:提交事务请求

    • 1.事务询问:协调者向所有的参与者发送事务内容,询问是否可以执行事务提交操作,并开始等待个参与者的响应。
    • 2.执行事务:各参与者节点执行事务操作,并将Undo和Redo信息计入事务日志中。
    • 3.各参与者向协调者反馈事务询问的响应 上面的过程是协调者组织各参与者对一次事务操作的投票表态过程,被称为“投票阶段”
  • 阶段二:执行事务提交

    • 执行事务提交:假如协调者从所有的参与者获得的反馈都是YES响应,那么就会执行事务提交
      • 1.发送提交请求:向各参与者发送commit请求
      • 2.事务提交:参与者接收到commit请求后,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期间占用的事务资源
      • 3.反馈事务提交结果
      • 4.完成事务:接收到所有参与者反馈的ACK消息,完成事务
        • 中断事务
        • 1.发送回滚请求:协调者发出Rollback请求
        • 2.事务回滚:利用Undo日志进行回滚操作,并在完成回滚之后释放整个事务执行期间占用的资源
        • 3.反馈事务回滚结果
        • 4.中断事务:接收到所有参与者反馈的ACK消息,中断事务

二阶段将一个事务的过程分为了投票执行两个阶段,其核心是对每个事务都采用先尝试后提交的处理方式,因此也可以将二阶段看作一个强一致性的算法。 图片来源于csdn

优缺点
  • 优点:原理简单,实现方便
  • 缺点:同步阻塞、单点问题、脑裂、太过保守

3PC

将2PC的提交事务请求过程一分为二,形成了由CanCommit、PreCommit和doCommit三个阶段组成的事务处理协议。

  • 阶段一:CanCommit
    • 1.事务询问:协调者发送一个包含事务内容的canCommit请求,询问是否可以执行事务提交操作,并开始等待各参与者的响应
    • 2.各参与者向协调者反馈事务询问的响应
  • 阶段二:PreCommit
    • 执行事务预提交
      • 1.发送预提交请求:协调者发送preCommit请求,进入PrePared阶段
      • 2.事务预提交:参与者接收到preCommit请求后,会执行事务操作,并将Undo和Redo信息记录到事务日志中。
      • 3.各参与者向协调者反馈事务执行的响应:提交或中止事务
    • 中断事务
      • 1.发送中断请求
      • 2.中断事务
  • 阶段三:doCommit
    • 执行提交
      • 1.发送提交请求:发送doCommit请求
      • 2.事务提交:接到doCommit请求,会正式执行事务提交操作,并在完成提交之后释放在整个事务执行期间占用的事务资源。
      • 3.反馈事务提交结果
      • 4.完成事务
    • 中断事务
      • 1.发送中断请求
      • 2.事务回滚:利用Undo日志来回滚事务,并在完成回滚之后释放在整个事务执行期间占用的资源
      • 3.反馈事务回滚结果
      • 4.中断事务 参与者都会在等待超时之后,继续进行事务提交 来自于wiki
        优缺点
  • 优点:降低了参与着的阻塞范围,并且能够在出现单点故障后继续达成一致
  • 缺点:在参与者接收到preCommit消息后,如果出现网络分区,此时协调者所在的节点和参与者无法进行正常的网络通信,在这种情况下,该参与者依然会进行事务的提交,这必然出现数据的不一致性。

一致性性算法Paxos

Proposer生成提案

以下是提案生成算法:

  • 1.Proposer选择一个新的提案编号Mn,然后向某个Acceptor集合的成员发送请求,要求该集合中的Acceptor做出如下回应:
    • 向Proposer承诺,保证不再批准任何编号小于Mn的提案
    • 如果Acceptor已经批准过任何提案,那么其就向Proposer反馈当前该Acceptor已经批准的编号小于Mn,但为最大编号的那个提案的值。

我们称该请求为编号为Mn提案的Prepare请求。

  • 2.如果Proposer收到了来自半数以上的Acceptor的响应结果,那么它就可以产生编号为Mn、Value值为Vn的提案,Vn就是所有响应中编号最大的提案的Value值。当然若没有半数以上Acceptor通过的提案,那此时Vn可以由Proposer指定。

Proposer批准提案

一个Acceptor可能会收到来自Proposer的两种请求,分别是Prepare请求和Accept请求,对着两类请求做出响应的条件分别如下:

  • Prepare请求:Acceptor可以在任何时候响应一个Prepare请求。
  • Accept请求:在不违背Accept现有承诺下,可以任意响应Accept请求。

对Acceptor的约束:

P1a:一个Acceptor只要尚未响应过任何编号大于Mn的Prepare请求,那么它就可以接受这个编号为Mn的提案。

算法称述

1.阶段一
+ 1.Proposer选择一个提案编号Mn,然后向Acceptor的某个超过半数的子集成员发送编号为Mn的Prepare请求;
+ 如果一个Acceptor收到一个编号为Mn的Prepare请求,且编号Mn大于该Acceptor已经提交的所有Prepare请求的编号,那么它就会将它已经批准过的最大编号的提案作为响应反馈给Proposer,同时该Acceptor会承诺不会再批准任何编号小于Mn的提案。
2.阶段2
+ 1.如果Proposer收到来自半数以上的Acceptor对于其发出的编号为Mn的Prepare请求的响应,那么它就会发出一个针对[Mn,Vn]提案的Accept请求给Acceptor.
+ 2.如果Acceptor收到这个针对[Mn,Vn]提案的Accept请求,只要该Acceptor尚未对编号大于Mn的Prepare请求做出响应,它就可以通过这个提案。

参考文献

results matching ""

    No results matching ""