一致性算法
Posted qmillet
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一致性算法相关的知识,希望对你有一定的参考价值。
一、何为分布式一致性
C(一致性)A(高可用)P(分区容错性)理论:在满足CP的基础上尽可能提高可用性。
何为一致性:一致性问题就是相互独立的节点之间如何达成一项决议的问题。分布式系统中,进行数据库事务提交(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:提议投票和接受者,只有在形成法定人数(Quorum,一般即为majority-多数派)时,提议才会最终被接受。像国会。
Learer:提议接受者,backup-备份,对集群一致性没什么影响。像记录员。
4.1.2 步骤
4.1.2.1 Prepare
proposer提出一个**提议,编号为N,**此N大于这个proposer之前提出的提案编号。请求acceptors的quorum接受。
4.1.2.2 Promise
如果N大于此acceptor之前接受的任何提案编号则接受,否则拒绝。
4.1.2.3 Accept
如果达到了多数派,proposer会发出 accept请求,此请求包含提案编号N,以及提案内容。
4.1.2.4 Accepted
如果此acceptor在此期间没有收到任何编号大于N的提案,则接受此提案内容,否则忽略。
Client Proposer Acceptor Learner | | | | | | | X-------->| | | | | | Request | X--------->|->|->| | | 4.2.1 Prepare(1) | |<---------X--X--X | | 4.2.2 Promise(1,{Va,Vb,Vc}) | X--------->|->|->| | | 4.2.3 Accept!(1,V) | |<---------X--X--X------>|->| 4.2.4 Accepted(1,V) |<---------------------------------X--X Response | | | | | | |
如果一个Acceptor宕机,只要满足多数派则可继续执行。
Client Proposer Acceptor Learner | | | | | | | X-------->| | | | | | Request | X--------->|->|->| | | Prepare(1) | | | | ! | | !! FAIL !! | |<---------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 Learner | | | | | | | --- First Request --- X-------->| | | | | | Request | X--------->|->|->| | | Prepare(N) N是提议版本 | |<---------X--X--X | | Promise(N,I,{Va,Vb,Vc}) I是Leader版本 | X--------->|->|->| | | Accept!(N,I,V) | |<---------X--X--X------>|->| Accepted(N,I,V) |<---------------------------------X--X Response | | | | | | |
------------------------------------------------------------------
Client Proposer Acceptor Learner
| | | | | | | --- Following Requests ---
X-------->| | | | | | Request
| X--------->|->|->| | | Accept!(N,I+1,W)
| |<---------X--X--X------>|->| Accepted(N,I+1,W)
|<---------------------------------X--X Response
| | | | | | |
------------------------------------------------------------------
Client Servers
X-------->| | | Request
| X->|->| Accept!(N,I+1,W)
| X<>X<>X Accepted(N,I+1)
|<--------X | | Response
| | | |
五、Raft
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——选主 操作。
5.2.2 Log Replication
1、所有的写请求都要经过Leader;
2、Leader将写请求携带在心跳包中发送给Follower;
3、当Leader收到多数派回复的消息后,则先自己提交写操作,同时发送Commit请求给Follower;
5.2.3 Safety保证
1、Leader宕机感知:
a、Raft通过TimeOut来保证Follower能正确感知Leader宕机或消息丢失的事件,并触发Follower竞选Leader;
b、Leader需要给Follower发送心跳包(heartbeats),数据也是携带在心跳包中发送给Follower的;
2、选主平票情况
Leader Election时平票情况下,则两个Candidates会产生一个随机的Timewait,继续发送下一个竞选消息。
3、脑裂(大小集群)情况:
小集群由于没有得到多数派的回复,写操作失败;
大集群会发生重新选主的过程,且新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则相反。
以上是关于一致性算法的主要内容,如果未能解决你的问题,请参考以下文章
有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]