2PC到3PC到Paxos到Raft到ISR

分布式理论系列node

本文主要讲述2PC及3PC,以及Paxos以及Raft协议。负载均衡

两类一致性(操做原子性与副本一致性)

  • 2PC协议用于保证属于多个数据分片上的操做的原子性。这些数据分片可能分布在不一样的服务器上,2PC协议保证多台服务器上的操做要么所有成功,要么所有失败。分布式

  • Paxos协议用于保证同一个数据分片的多个副本之间的数据一致性。当这些副本分布到不一样的数据中心时,这个需求尤为强烈。性能

1、2PC(阻塞、数据不一致问题、单点问题)

Two-Phase Commit,两阶段提交

一、阶段一:提交事务请求(投票阶段)

(1)事务询问

协调者向全部的参与者发送事务内容,询问是否能够执行事务提交操做,并开始等待各参与者的响应

(2)执行事务

各参与者节点执行事务操做,并将Undo和Redo信息计入事务日志中

(3)各参与者向协调者反馈事务询问的响应

若是参与者成功执行了事务操做,那么就反馈给协调者Yes响应,表示事务能够执行;若是参与者没有成功执行事务,那么就反馈给协调者No响应,表示事务不能够执行。

二、阶段二:执行事务提交(执行阶段)

(1)执行事务提交

若是全部参与者的反馈都是Yes响应,那么
  • A、发送提交请求

    协调者向全部参与者节点发出Commit请求
  • B、事务提交

    参与者接收到Commit请求后,会正式执行事务提交操做,并在完成提交以后释放在整个事务执行期间占用的事务资源
  • C、反馈事务提交结果

    参与者在完成事务提交以后,向协调者发送ACK信息
  • D、完成事务

    协调者接收到全部参与者反馈的ACK消息后,完成事务

(2)中断事务

任何一个参与者反馈了No响应,或者在等待超时以后,协调者尚没法接收到全部参与者的反馈响应,那么就会中断事务。
  • A、发送回滚请求

    协调者向全部参与者节点发出Rollback请求
  • B、事务回滚

    参与者接收到rollback请求后,会利用其在阶段一中记录的Undo信息来执行事务回滚操做,并在完成回滚以后释放整个事务执行期间占用的资源
  • C、反馈事务回滚结果

    参与者在完成事务回滚以后,向协调者发送ACK信息
  • D、中断事务

    协调者接收到全部参与者反馈的ACK信息后,完成事务中断

优缺点

优势:原理简单、实现方便
缺点:同步阻塞、单点问题、数据不一致、太过保守

  • (1)同步阻塞
    同步阻塞会极大地限制分布式系统的性能。在二阶段提交的执行过程当中,全部参与该事务操做的逻辑都处于阻塞状态,各个参与者在等待其余参与者响应的过程当中,将没法进行其余任何操做。

  • (2)单点问题
    一旦协调者出现问题,那么整个二阶段提交流程将没法运转,更为严重的是,若是是在阶段二中出现问题,那么其余参与者将会一直处于锁定事务资源的状态中,没法继续完成事务操做。

  • (3)数据不一致
    在阶段二,当协调者向全部参与者发送commit请求以后,发生了局部网络异常或协调者在还没有发完commit请求以前自身发生了崩溃,致使最终只有部分参与者接收到了commit请求,因而这部分参与者执行事务提交,而没收到commit请求的参与者则没法进行事务提交,因而整个分布式系统出现了数据不一致性现象。

  • (4)太过保守
    若是参与者在与协调者通讯期间出现故障,协调者只能靠超时机制来判断是否须要中断事务,这个策略比较保守,须要更为完善的容错机制,任意一个节点的失败都会致使整个事务的失败。

过程示意图以下:

2、3PC(解决2PC的阻塞,但仍是可能形成数据不一致)

Three-Phase Commit,三阶段提交,分为CanCommit、PreCommit、do Commit三个阶段。

为了不在通知全部参与者提交事务时,其中一个参与者crash不一致时,就出现了三阶段提交的方式。三阶段提交在两阶段提交的基础上增长了一个preCommit的过程,当全部参与者收到preCommit后,并不执行动做,直到收到commit或超过必定时间后才完成操做。

一、阶段一CanCommit

  • (1)事务询问
    协调者向各参与者发送CanCommit的请求,询问是否能够执行事务提交操做,并开始等待各参与者的响应

  • (2)参与者向协调者反馈询问的响应
    参与者收到CanCommit请求后,正常状况下,若是自身认为能够顺利执行事务,那么会反馈Yes响应,并进入预备状态,不然反馈No。

二、阶段二PreCommit

(1)执行事务预提交

若是协调者接收到各参与者反馈都是Yes,那么执行事务预提交
  • A、发送预提交请求
    协调者向各参与者发送preCommit请求,并进入prepared阶段

  • B、事务预提交
    参与者接收到preCommit请求后,会执行事务操做,并将Undo和Redo信息记录到事务日记中

  • C、各参与者向协调者反馈事务执行的响应
    若是各参与者都成功执行了事务操做,那么反馈给协调者Ack响应,同时等待最终指令,提交commit或者终止abort

(2)中断事务

若是任何一个参与者向协调者反馈了No响应,或者在等待超时后,协调者没法接收到全部参与者的反馈,那么就会中断事务。

  • A、发送中断请求

    协调者向全部参与者发送abort请求
  • B、中断事务

    不管是收到来自协调者的abort请求,仍是等待超时,参与者都中断事务

三、阶段三doCommit

(1)执行提交

  • A、发送提交请求
    假设协调者正常工做,接收到了全部参与者的ack响应,那么它将从预提交阶段进入提交状态,并向全部参与者发送doCommit请求

  • B、事务提交
    参与者收到doCommit请求后,正式提交事务,并在完成事务提交后释放占用的资源

  • C、反馈事务提交结果
    参与者完成事务提交后,向协调者发送ACK信息

  • D、完成事务
    协调者接收到全部参与者ack信息,完成事务

(2)中断事务

假设协调者正常工做,而且有任一参与者反馈No,或者在等待超时后没法接收全部参与者的反馈,都会中断事务

  • A、发送中断请求
    协调者向全部参与者节点发送abort请求

  • B、事务回滚
    参与者接收到abort请求后,利用undo日志执行事务回滚,并在完成事务回滚后释放占用的资源

  • C、反馈事务回滚结果
    参与者在完成事务回滚以后,向协调者发送ack信息

  • D、中断事务
    协调者接收到全部参与者反馈的ack信息后,中断事务。

阶段三可能出现的问题:
协调者出现问题、协调者与参与者之间网络出现故障。不论出现哪一种状况,最终都会致使参与者没法及时接收到来自协调者的doCommit或是abort请求,针对这种状况,参与者都会在等待超时后,继续进行事务提交(timeout后中断事务)。

 

优势:下降参与者阻塞范围,并可以在出现单点故障后继续达成一致
缺点:引入preCommit阶段,在这个阶段若是出现网络分区,协调者没法与参与者正常通讯,参与者依然会进行事务提交,形成数据不一致。

 

过程示意图以下:

 

3、Paxos(解决单点问题)

基于消息传递且具备高度容错性的一致性算法。Paxos算法要解决的问题就是如何在可能发生几起宕机或网络异常的分布式系统中,快速且正确地在集群内部对某个数据的值达成一致,而且保证不论发生以上任何异常,都不会破坏整个系统的一致性。

拜占庭问题:消息不完整或者被篡改。Paxos在维持领导者选举或者变量修改一致性上,采起一种相似议会投票的过半赞成机制,好比设定一个领导者,须要将此看作一个议案,征求过半赞成,每一个节点经过一个议案会有编号记录,再次收到此领导者的不一样人选,发现已经有编号记录便驳回,最后以多数经过的结果为准。

 

咱们举个简单的例子,来阐述一下Paxos的基本思想:假设咱们有5台计算机A、B、C、D、E,每台计算机保存着公司CEO的信息,如今CEO任期到了,须要进行新一界选举了。

A计算机发起一个选举议案,提议CEO为“张三”,若是没有其余候选人议案,也没有网络问题,只要其中半数以上计算机收到并经过议案,那么最终“张三”当选CEO。因为是分布式环境,并发请求、机器故障、网络故障等问题是常态,若是A和E同时提交选举议案,A提名“张三”,E提名“李四”,那么确定会涉及多计算机的一致性问题了:假设A、B、C先收到A的议案,D、E先收到E的议案,那么A继续提交给D时,D告诉它已经先收到E的议案了,所以驳回了A的请求。一样E继续提交给A、B、C时也碰到相同的问题。

咱们能够经过“在每台计算机同时接受议案提交时设置一个编号,编号先的经过,编号后的驳回”的方式来实现。议案提交上去后,发现A、B、C投票“张三”为CEO,D、E投票“李四”为CEO,少数服从多数,所以最后结果为“张三”当选CEO。

若是是C计算机发生了网络问题或者故障,双方投票相同,那么选举没法完成。

若是C计算机发生了网络问题或者故障,A、B、D投票“张三”,E投票“李四”,那么结果为“张三”当选,而C对于这些状况一无所知,可是当C计算机恢复正常时,他会发起一个“询问谁是CEO”的议案获取最新信息。简言之,Paxos对每一个节点的并发修改采起编号记录的方式保持一致性,对多个节点的并发修改采起少数服从多数的方式保持一致性。Paxos有点相似分布式二阶段提交方式,可是又不一样,二阶段提交不能是多数节点赞成,必须是所有赞成。为了遵照过半节点赞成的约束,Paxos算法每每要求节点总数为奇数。

Paxos 算法解决的问题是在一个可能发生上述异常的分布式系统中如何就某个值达成一致,保证不论发生以上任何异常,都不会破坏决议的一致性。一个典型的场景是,在一个分布式数据库系统中,若是各节点的初始状态一致,每一个节点都执行相同的操做序列,那么他们最后能获得一个一致的状态。为保证每一个节点执行相同的命令序列,须要在每一条指令上执行一个「一致性算法」以保证每一个节点看到的指令一致。一个通用的一致性算法能够应用在许多场景中,是分布式计算中的重要问题。从20世纪80年代起对于一致性算法的研究就没有中止过。

 

简单说来,Paxos的目的是让整个集群的结点对某个值的变动达成一致。Paxos算法基本上来讲是个民主选举的算法——大多数的决定会成个整个集群的统一决定。任何一个点均可以提出要修改某个数据的提案,是否经过这个提案取决于这个集群中是否有超过半数的结点赞成(因此Paxos算法须要集群中的结点是单数)。

这个算法有两个阶段(假设这个有三个结点:A,B,C):

第一阶段:Prepare阶段

A把申请修改的请求Prepare Request发给全部的结点A,B,C。注意,Paxos算法会有一个Sequence Number(你能够认为是一个提案号,这个数不断递增,并且是惟一的,也就是说A和B不可能有相同的提案号),这个提案号会和修改请求一同发出,任何结点在“Prepare阶段”时都会拒绝其值小于当前提案号的请求。因此,结点A在向全部结点申请修改请求的时候,须要带一个提案号,越新的提案,这个提案号就越是是最大的。

若是接收结点收到的提案号n大于其它结点发过来的提案号,这个结点会回应Yes(本结点上最新的被批准提案号),并保证不接收其它<n的提案。这样一来,结点上在Prepare阶段里老是会对最新的提案作承诺。

 

优化:在上述 prepare 过程当中,若是任何一个结点发现存在一个更高编号的提案,则须要通知 提案人,提醒其中断此次提案。

第二阶段:Accept阶段

若是提案者A收到了超过半数的结点返回的Yes,而后他就会向全部的结点发布Accept Request(一样,须要带上提案号n),若是没有超过半数的话,那就返回失败。

当结点们收到了Accept Request后,若是对于接收的结点来讲,n是最大的了,那么,它就会经过request(修改这个值),若是发现本身有一个更大的提案号,那么,结点就会拒绝request(拒绝修改)。

咱们能够看以,这彷佛就是一个“两段提交”的优化。其实,2PC/3PC都是分布式一致性算法的残次版本,Google Chubby的做者Mike Burrows说过这个世界上只有一种一致性算法,那就是Paxos,其它的算法都是残次品。

咱们还能够看到:对于同一个值的在不一样结点的修改提案就算是在接收方被乱序收到也是没有问题的。

4、Raft协议(解决paxos的实现难度)

Paxos 相比 Raft 比较复杂和难以理解。角色扮演和流程比 Raft 都要啰嗦。好比 Agreement 这个流程,在 Paxos 里边:Client 发起请求举荐 Proposer 成为 Leader,Proposer 而后向全局 Acceptors 寻求确认,Acceptors 所有赞成 Proposer 后,Proposer 的 Leader 地位得已认可,Acceptors 还得再向Learners 进行全局广播来同步。而在 Raft 里边,只有 Follower/Candidate/Leader 三种角色,角色自己表明状态,角色之间进行状态转移是一件很是自由民主的事情。Raft虽然有角色之分可是是全民参与进行选举的模式;可是在Paxos里边,感受更像议员参政模式。

三个角色

follower、candidate、leader。
最开始你们都是follower,当follower监听不到leader,就能够本身成为candidate,发起投票

leader选举:timeout限制

选举的timeout

follower成为candidate的超时时间,每一个follower都在150ms and 300ms之间随机,以后看谁先timeout,谁就先成为candidate,而后它会先投本身一票,再向其余节点发起投票邀请。
若是其余节点在这轮选举尚未投过票,那么就给candidate投票,而后重置本身的选举timeout。
若是获得大多数的投票就成为leader,以后按期开始向follower发送心跳。

若是两个follower同时成为candidate的话,若是最后获得的票数相同,则等待其余follower的选择timeout以后成为candidate,继续开始新一轮的选举。

log复制

leader把变更的log借助心跳同步给follower,过半回复以后才成功提交,以后再下一次心跳以后,follower也commit变更,在本身的node上生效。

分裂以后,另外一个分区的follower接受不到leader的timeout,而后会有一个先timeout,成为candidate,最后成为leader。
因而两个分区就有了两个leader。

 

当客户端有变更时,其中的leader因为没法收到过半的提交,则保持未提交状态。有的leader的修改,能够获得过半的提交,则能够修改生效。

当分裂恢复以后,leader开始对比选举的term,发现有更高的term存在时,他们会撤销未提交的修改,而后以最新的为准。

5、ISR的机制(解决f容错的2f+1成本问题)

Kafka并无使用Zab或Paxos协议的多数投票机制来保证主备数据的一致性,而是提出了ISR的机制(In-Sync Replicas)的机制来保证数据一致性。

ISR认为对于2f+1个副原本说,多数投票机制要求最多只能容许f个副本发生故障,若是要支持2个副本的容错,则须要至少维持5个副本,对于消息系统的场景来讲,效率过低。

ISR的运行机制以下:将全部次级副本数据分到两个集合,其中一个被称为ISR集合,这个集合备份数据的特色是即时和主副本数据保持一致,而另一个集合的备份数据容许其消息队列落后于主副本的数据。在作主备切换时,只容许从ISR集合中选择主副本,只有ISR集合内全部备份都写成功才能认为此次写入操做成功。在具体实现时,kafka利用zookeeper来保持每一个ISR集合的信息,当ISR集合内成员变化时,相关构件也便于通知。经过这种方式,若是设定ISR集合大小为f+1,那么能够最多容许f个副本故障,而对于多数投票机制来讲,则须要2f+1个副本才能达到相同的容错性。

 

参考资料:

https://segmentfault.com/a/1190000004474543

https://blog.csdn.net/jianghuiyun/article/details/80461374

相关文章
相关标签/搜索