zoukankan      html  css  js  c++  java
  • 一致性算法

    参考链接1 --分布式系列文章

    参考连接2

    一、何为分布式一致性

      C(一致性)A(高可用)P(分区容错性)理论:在满足CP的基础上尽可能提高可用性。

    • 一致性(Consistency) : 客户端知道一系列的操作都会同时发生(生效)
    • 可用性(Availability) : 每个操作都必须以可预期的响应结束
    • 分区容错性(Partition tolerance) : 即使出现单个组件无法可用,操作依然可以完成

      何为一致性:一致性问题就是相互独立的节点之间如何达成一项决议的问题。分布式系统中,进行数据库事务提交(commit transaction)、Leader选举、序列号生成等都会遇到一致性问题(多数者理论,法院提案选举)。

      一致性又分为弱一致性(最终一致性,即最终结果对了就行)和强一致性。

       弱一致性有DNS、Gossip实现。

       强一致性可分为两类:

        1.主从同步,可参考Mysql主从同步,Master接受写请求,复制日志到slave,Master等待,直到所有从库返回。但是如果一个节点失败,Master就会阻塞,导致整个集群不可用。

        2.多数派,每次写都保证写入大于N/2个节点,每次读保证从大于N/2个节点中读。相关算法:Paxos、Raft(multi-paxos)、ZAB(multi-paxos)

      什么样的系统才能满足一致性要求:

        1.全认同:所有节点都认同一个结果。

        2.值合法:结果必须由节点内部提出。

        3.可结束:决议过程在一定时间内可结束。

      分布式系统面临的问题:

        1.消息会出现延时、丢失,节点消息间不能做到同步有序。

        2.节点宕机或者出现逻辑问题。

        3.网络分化,即将节点分区。

    二、2PC-tow phase commit  

    1.角色划分:

      coordinator(协调者):提出提议的节点。

      participants/cohorts(参与者):参与决议的节点。

    2.两阶段划分:

      在阶段一中,协调者发起一个提议,分别询问参与者是否接受。

     

      在阶段二中,协调者根据参与者的反馈,提交或者终止事务。如果参与者全部同意则提交事务,只要有一个参与者不同意就终止事务。

    3.存在问题

      协调者如果发起提议后宕机,那么参与者会进入阻塞状态,等待参与者回应完成此次决议。此时需要一个协调者备份角色解决此问题,协调者宕机一段时间后,协调者备份接替协调者的工作,通过问询参与者的状态决定阶段2是否提交事务。这也要求协调者/参与者记录历史状态,以备协调者备份对参与者查询。重新恢复状态。

    三、3PC-three phase commit

      三阶段提交增加了一个准备提交(prepare to commit)阶段解决patticpant宕机问题。

      具体过程如下图:

    四、Paxos

    4.1 Basic Paxos

    4.1.1 角色划分

      Client:系统外部角色。请求发起者——民众。

      Proposer:接受Client请求,向集群提出提议(propose),并在冲突发生时,起到冲突调解的作用。像议员,替民众提出议案。

      Acceptor:提议投票和接受者,只有在形成法定人数(一般为多数派)时,提议才会最终被接受。像国会。

      Learer:提议接受者,backup-备份,对集群一致性没什么影响。像记录员。

    4.1.2 步骤

      阶段一

        Prepare:proposer提出一个**提议,编号为N,**此N大于这个proposer之前提出的提案编号。请求acceptors的quorum接受。

        Promise:如果N大于此acceptor之前接受的任何提案编号则接受(保证当前提案是最新的一个),否则拒绝。

      阶段二

         Accept:如果达到了多数派(多数派),proposer会发出 accept请求,此请求包含提案编号N,以及提案内容。

        Accepted:如果此acceptor在此期间没有收到任何编号大于N的提案(保证处理提案期间没有新的提案),则接受此提案内容,否则忽略。

       处理请求的节点   参与投票的三个节点  相当于复制节点
    Client Proposer Acceptor Learner Va、Vb、Vc看作三台实例
    | | | | | | | X-------->| | | | | | Request //client通过processer向整个分布式系统发出请求 | X--------->|->|->| | | 4.2.1 Prepare(1) // 好的我们同意准备处理请求 | |<---------X--X--X | | 4.2.2 Promise(1,{Va,Vb,Vc}) // 提案最新,接受 | X--------->|->|->| | | 4.2.3 Accept!(1,V) // 达到了多数派,接受请求 // acceptor写入数据 | |<---------X--X--X------>|->| 4.2.4 Accepted(1,V) //此期间没有收到比1大的提案,接受 //Leaner写入 |<---------------------------------X--X Response | | | | | | |

      如果一个Acceptor宕机,只要满足多数派则可继续执行。

    Client   Proposer      Acceptor     Learner
       |         |          |  |  |       |  |
       X-------->|          |  |  |       |  |  Request
       |         X--------->|->|->|       |  |  Prepare(1)
       |         |          |  |  !       |  |  !! FAIL !!                       //此时C宕机
       |         |<---------X--X          |  |  Promise(1,{Va, Vb, null})
       |         X--------->|->|          |  |  Accept!(1,V)
       |         |<---------X--X--------->|->|  Accepted(1,V)
       |<---------------------------------X--X  Response
       |         |          |  |          |  |

      如果Learner宕机,可继续执行成功。

    Client Proposer         Acceptor     Learner
       |         |          |  |  |       |  |
       X-------->|          |  |  |       |  |  Request
       |         X--------->|->|->|       |  |  Prepare(1)
       |         |<---------X--X--X       |  |  Promise(1,{Va,Vb,Vc})
       |         X--------->|->|->|       |  |  Accept!(1,V)
       |         |<---------X--X--X------>|->|  Accepted(1,V)
       |         |          |  |  |       |  !  !! FAIL !!
       |<---------------------------------X     Response
       |         |          |  |  |       |

      如果一个Proposser在提出提议后宕机,会选出新的Leader接收Accepor反馈。

    Client  Proposer        Acceptor     Learner
       |      |             |  |  |       |  |
       X----->|             |  |  |       |  |  Request
       |      X------------>|->|->|       |  |  Prepare(1)
       |      |<------------X--X--X       |  |  Promise(1,{Va, Vb, Vc})
       |      |             |  |  |       |  |
       |      |             |  |  |       |  |  !! Leader fails during broadcast !!
       |      X------------>|  |  |       |  |  Accept!(1,V)
       |      !             |  |  |       |  |
       |         |          |  |  |       |  |  !! NEW LEADER !!     //换一个新的
       |         X--------->|->|->|       |  |  Prepare(2)                             //换一个提案编号,上一个已经用过了
       |         |<---------X--X--X       |  |  Promise(2,{V, null, null})
       |         X--------->|->|->|       |  |  Accept!(2,V)
       |         |<---------X--X--X------>|->|  Accepted(2,V)
       |<---------------------------------X--X  Response
       |         |          |  |  |       |  |

    4.1.3 存在问题

      4.1.3.1 活锁和dueing(决斗

        多个Prosesser提议者都认为自己是领导者,例如Prosesser1发出提议1之后,Prosesser2也发出提议2,此时Prosesser1的提议就会被拒绝,会再次发出提议3,然后Prosesser2的提议2就会被拒绝发出提议4、、、、

      

    Client   Leader         Acceptor     Learner
    |      |             |  |  |       |  |
    X----->|             |  |  |       |  |  Request
    |      X------------>|->|->|       |  |  Prepare(1)
    |      |<------------X--X--X       |  |  Promise(1,{null,null,null})
    |      !             |  |  |       |  |  !! LEADER FAILS
    |         |          |  |  |       |  |  !! NEW LEADER (knows last number was 1)
    |         X--------->|->|->|       |  |  Prepare(2)
    |         |<---------X--X--X       |  |  Promise(2,{null,null,null})
    |      |  |          |  |  |       |  |  !! OLD LEADER recovers
    |      |  |          |  |  |       |  |  !! OLD LEADER tries 2, denied
    |      X------------>|->|->|       |  |  Prepare(2)
    |      |<------------X--X--X       |  |  Nack(2)
    |      |  |          |  |  |       |  |  !! OLD LEADER tries 3
    |      X------------>|->|->|       |  |  Prepare(3)
    |      |<------------X--X--X       |  |  Promise(3,{null,null,null})
    |      |  |          |  |  |       |  |  !! NEW LEADER proposes, denied
    |      |  X--------->|->|->|       |  |  Accept!(2,Va)
    |      |  |<---------X--X--X       |  |  Nack(3)
    |      |  |          |  |  |       |  |  !! NEW LEADER tries 4
    |      |  X--------->|->|->|       |  |  Prepare(4)
    |      |  |<---------X--X--X       |  |  Promise(4,{null,null,null})
    |      |  |          |  |  |       |  |  !! OLD LEADER proposes, denied
    |      X------------>|->|->|       |  |  Accept!(3,Vb)
    |      |<------------X--X--X       |  |  Nack(4)
    |      |  |          |  |  |       |  |  ... and so on ...

      解决办法:如果发生冲突,则Proposer等待一个Random的Timeout(一般几秒)再提交自己的提议。

      4.1.3.2 难实现,效率低

      Basic Paxos的难度是较为出名的,且不易理解。提交提议、提交提案(日志)内容进行了两轮RTT操作,效率较低。 

    4.2 Multi Paxos

    4.2.1 角色

      Leader:唯一的Prosesser,不会有争夺了,所有请求都需经过此Leader。

      Client:客户端

      Server:服务端

    4.2.2 实现过程

    Client   Proposer      Acceptor     LearnerLeader
    |         |          |  |  |       |  | --- First Request ---
    X-------->|          |  |  |       |  |  Request
    |         X--------->|->|->|       |  |  Prepare(N)   N是Leader版本,需要竞选一次,如果后面期间Leader挂了,再选一个
    |         |<---------X--X--X       |  |  Promise(N,I,{Va,Vb,Vc}) 
    |         X--------->|->|->|       |  |  Accept!(N,I,V)
    |         |<---------X--X--X------>|->|  Accepted(N,I,V)
    |<---------------------------------X--X  Response
    |         |          |  |  |       |  |

    ------------------------------------------------------------------
    Client   Proposer       Acceptor     Learner
    |         |          |  |  |       |  |  --- Following Requests ---  下面请求不用在选Leader
    X-------->|          |  |  |       |  |  Request
    |         X--------->|->|->|       |  |  Accept!(N,I+1,W)
    |         |<---------X--X--X------>|->|  Accepted(N,I+1,W)
    |<---------------------------------X--X  Response
    |         |          |  |  |       |  |
    ----------------------------进一步简化--------------------------------------
    直接由Server内部进行选举leader
    Client      Servers
    X-------->|  |  |  Request
    |         X->|->|  Accept!(N,I+1,W)
    |         X<>X<>X  Accepted(N,I+1)
    |<--------X  |  |  Response
    |         |  |  |

    五、Raft

    动画显示:http://thesecretlivesofdata.com/raft/        https://raft.github.io/

    5.1 角色

      Leader:主节点,整个集群只有一个Leader,所有的写请求都通过Leader发送给Follower;在每一个Leader的任期期间,都有唯一表示该任期的Term。

      Follower:从节点(服从角色);

      Candidate:在Leader消息发送失败或宕机,整集群没有Leader时,此时Follower接收Leader的心跳包失败,则Follwer开始竞选Leader时,它们的身份是Candidate。Candidate只是个中间状态,不会长期存在

    5.2 基本过程

    5.2.1 Leader Election_选举☆☆☆☆☆☆

      集群启动或Leader的心跳包消息无法发送给Follower时,触发 Leader Election——选主 操作。

      每一个节点都有一个随机timeout,当到了timeout时间还没有收到Leader的心跳包的话,那么当前节点就会向其他节点发送一个竞选Leader的请求。如果多数同意(此时其他节点的timeout还没到,例如三个节点tieout分别为 1s, 2s,3s,一号节点1s刷新一次,肯定是他先探测到Leader宕机,因此它第一个竞选Leader,成为第一个候选人),那么当前节点成功竞选为leader,向其他节点发送心跳包。

    5.2.2 Log Replication_复制数据  (两阶段提交)☆☆☆☆☆

      1、所有的写请求都要经过Leader;
      2、Leader将写请求log携带在心跳包中发送给Follower;

      3. 节点保存log并未执行,回复Leader;
      4、当Leader收到多数派回复的消息后,则先自己提交写操作,同时发送Commit请求给Follower;

    5.3 Leader选举Safety保证_安全保障 

     1、Leader宕机感知:
      a、Raft通过TimeOut来保证Follower能正确感知Leader宕机或消息丢失的事件,并触发Follower竞选Leader;
      b、Leader需要给Follower发送心跳包(heartbeats),数据也是携带在心跳包中发送给Follower的;

     2、选主平票情况--两个节点Timeout同时到期,都是第一候选者
      Leader Election时平票情况下,则两个Candidates会产生一个随机的Timewait,继续发送下一个竞选消息。

     3、脑裂(大小集群)情况:看动画演示

      五个节点集群,分成了3+2,每个集群都有一个Leader,造成了整个集群有两个Leader。当对两个Leader进行写操作时:
      小集群(2节点)由于没有得到多数派的回复(只收到一个),写操作失败;

      大集群会发生重新选主的过程,且新Leader拥有自己新的Term(任期),写操作成功;
      当小集群回到大集群时,由于小集群的Term小于新集群的Term,则同步新集群的信息。

    5.3 一致性 = 客户端 + 一致性算法

     Client Request操作的三个可能结果:成功、失败、unknown(Timeout)

     5.3.1理解unknown(Timeout)
      场景:Client写请求,Leader向Follower同步日志,此时集群中有3个节点失败,2个节点存活,结果是? 假设节点为:S1、S2、S3、S4、S5(Leader)

      假设S5和S4存活,Client发起 第N次写请求 为 操作I 时,由于Leader没有得到多数派的回复,操作I只被发送到了S4中,此时Leader即会返回Client unknown,因为Leader不知道后面会不会成功将该条日志写入多数派中。
      结果1:假设Leader在返回客户端后,宕机的Follower:S1、S2、S3恢复正常,Leader再次发送 第N次写请求——操作I,且得到了多数派的回复,则提交日志,写操作最终结果为成功;
      结果2:假设Leader在返回客户端后,此时S5和S4宕机,且S1、S2、S3恢复正常,此时S1、S2、S3触发选主操作,且集群恢复可用,如果此时Client发起 第N+1次请求 为 操作I+1 ,且Client操作成功后 S5、S4恢复正常,则保存在S5、S4中的 操作I 会被删除,S5、S4同步最新的 操作I+1 到本地。则 第N次写请求—操作I 失败;

      总结:一致性需要客户端和共识算法(Consensus)来共同保证。

    六、ZAB - Zookeeper atomic broadcast protocol
      ZAB是Zookeeper内部用到的一致性协议。基本与Raft相同。  在一些名词的叫法上有些区别:如ZAB将某一个leader的周期(任期)称为epoch,而Raft则称为Term。实现上也有些许不同:Raft保证日志连续性,心跳方向为Leader至Follower。ZAB则相反。

  • 相关阅读:
    UVALive 4764 简单dp水题(也可以暴力求解)
    poj 2151 概率DP(水)
    poj 2299 归并排序求逆序数 (可做模板)
    poj2388 更水
    poj1936 假期计划第一水
    poj 3080 kmp求解多个字符串的最长公共字串,(数据小,有点小暴力 16ms)
    UVA315:Network(求割点)
    POJ1236:Network of Schools (思维+Tarjan缩点)
    SPOJ
    HDU4305:Lightning(生成树计数+判断点是否在线段上)
  • 原文地址:https://www.cnblogs.com/qmillet/p/12487412.html
Copyright © 2011-2022 走看看