什么是CAP关于CAP理论的背景介绍已经有很多了,这里就不过多介绍了。让我们谈谈如何理解它。用通俗易懂的术语解释这三个术语:一致性如果你刚刚写入一个节点,那么你必须读取另一个节点刚刚写入的数据,而不是更旧的数据。可用性如果一个节点被请求,该节点必须能够响应。如果节点挂了,就没有可用性。Partitiontolerance是否容忍网络分区,即允许节点不能与其他节点通信。CAP的意思是我们只能保证最多同时有两个条件为真。让我们看看为什么。如图所示,如果我们满足分区容忍度,即虚线表示两个节点已经分区。如果要满足一致性,那么只能暂时挂起请求其他节点的操作,返回客户端失败或者超时的结果。这种情况多发生在银行柜台等对数据一致性要求高的情况。因为保证用户资金的正确性比暂时禁止用户操作更重要。如果要满足可用性,因为网络已经被隔离了,没办法做到一致性。这种情况经常出现在互联网行业,比如新闻,数据一致性不高但是可用性高。毕竟,用户根本看不到新闻,比看不到及时的新闻更重要。你可以自由组合,最终证明三个条件不能同时满足。事实上,在大多数情况下,我们只是在一致性和可用性之间进行选择。一致性=共识?一致性几乎被业界用坏了,以至于我们在讨论一致性的时候,其实并不确定对方说的一致性和我们自己的是否一致。Consistency:一致性,Consensus:协同,这两个概念很容易混淆。一致性,我们常说的,指的是分布式系统中同一份数据的多份副本。描述副本问题的一致性。共识(Consensus)则不同。简单来说,共识问题就是需要多个节点通过一定的算法达到相同状态的过程。在我看来,一致性强调结果,共识强调过程。共识?状态机?KenThompson共识有一个更引人注目的名字:基于状态机复制的共识算法那么,什么是状态机呢?状态机是有限状态自动机的简称,它是从现实事物的运行规则中抽象出来的一种数学模型。看下图,门有两种状态,打开和关闭。因此,在我看来,state是静态的场景,transition赋予它动态的变化。以此类推,如果一个节点当前的数据是X,现在有add+1的操作日志,那么当前状态就是X+1,好了,状态(X)已经改变了(操作日志)有了那个,这是状态机。分布式共识,简单来说就是一个或多个节点提出一个状态应该是什么后,系统中所有节点就一个状态达成共识的全过程。共识是过程,一致性是结果。共识模型主从同步:我们都知道MySQL等业界常见数据库的主从同步(Master-SlaveReplication)。主从同步分为三个阶段:Master接受写请求,Master复制日志给SlaveMaster等待所有从库返回。由此可见,主从同步模型存在一个致命的问题:只要有一个节点出现故障,Master就会被阻塞,导致整个集群不可用,保证了一致性,大大降低了可用性。多数:每次写入大于N/2个节点,每次读取也保证从N/2个节点读取。多数模型似乎完美解决了多节点一致性问题。不只是性能差,但是在并发的情况下就不一定了,如下图:在并发环境下,因为各个节点的操作日志的写入顺序无法保证要一致,不能保证最终的一致性。如图所示,对三个节点inc5和??set0有两个操作,但是因为顺序不同,其中两个最终状态是0,一个是5。因此,我们需要引入一种机制,对每个操作日志进行编号,并且这个数是从小到大生成的,这样每个节点都不会出错。(有没有想过在网络中分包重组?)那么,现在关键问题又来了,这个号怎么协调?看来这是一个先有鸡还是先有蛋的问题。PaxosPaxos模型试图探索更一般形式的分布式共识问题。Latex的发明者LesileLamport提出了Paxos算法。他创造了一个虚构的希腊城邦Paxos,一个按照议会民主政治模式制定法律的岛屿,但没有人愿意把所有的时间和精力都投入到这件事上。因此,无论是国会议员、议长,还是送纸条的服务员,都不能承诺别人需要的时候出现,也不能承诺后者在通过决议后传递信息的时间。因为Paxos太难懂了,Lamport觉得他的同事听不懂他的幽默感,于是他后来重新发布了一个通俗版的算法描述《Paxos Made Simple》。总体来说,共识算法有两个阶段,如图所示,第一阶段是proposal,第二阶段是decision。为了在分布式系统中实现容错,需要一个共识模型,而节点之间达成共识不仅需要节点之间的算法,还取决于客户端的行为。例如,即使副本系统使用multi-paxos同步所有副本服务器上的日志序号,如果允许Client从非Leader节点写入数据,整个副本系统仍然不强一致。接下来重头戏来了,详细介绍一下Paxos。角色介绍:Client:系统的外部角色,请求发起者。比如人。Proposer:接受Client请求,向集群提出建议。而当冲突发生时,它起到调解冲突的作用。比如国会议员,为人民提出议案。Accpetor:提案投票和接受者。只有形成法定人数(Quorum,Majoritymajority),提案才会最终被接受。比如国会。Learner:proposalrecipient,backup,backup,对集群的一致性没有影响。比如录音机。步骤、阶段:1.Phase1a:Prepareproposer提出一个提案,编号为N,N必须大于proposer之前提出的提案的编号,并请求quorum(最多)的acceptor接受。2.Phase1b:如果N大于这个acceptor之前接受过的任何proposalnumber,Promise接受,否则拒绝。3.Phase2a:如果Accept达到多数,proposer将发送一个acceptrequest,其中包含上一步的proposalnumber和proposalcontent。4.Phase2b:Accepted如果acceptor在此期间没有收到任何大于N的提案,则接受该提案内容,否则忽略。还记得我们上面提到同步编号是一个很重要的问题,绿色方框其实就是同步编号的过程。通过这个编号,可以知道每条操作日志的先后顺序。简单来说,第一阶段就是获取数,第二阶段就是写入日志。可以看出Paxos采用了两轮交互,牺牲了时间和性能来弥补一致性问题。现在我们考虑一些节点宕机的场景。由于多数接受者达成共识,第一阶段还是成功拿到了号码,最后一切顺利。考虑提议者宕机的场景。没关系,虽然第一个proposer失败了,但是下一个proposer使用了更大的proposalnumber,所以下一个proposer最终还是成功了,可用性和一致性还是有保证的。潜在问题:LivelockPaxos存在活锁问题。如图所示,当第一个proposer在第一阶段发出请求时,在后续的第二阶段请求之前,第二个proposer也在第一阶段发出请求。如果这样没完没了,acceptor会一直停留在decisionorder中,在编号的过程中,你们谁都不能成功。遇到这样的问题,其实很好解决。如果发现序列号被新的提议者更新,则引入随机等待超时时间,避免多个提议者冲突。MultiPaxos由于Paxos存在问题:难以实现、效率低(2轮rpc)、livelock。因此,MultiPaxos被引入。MultiPaxos引入了Leader,它是唯一的提议者。所有的请求都必须经过这个Leader。因为只有一个节点维护提案编号,所以省略了第一轮讨论提案编号的过程。然后进一步简化角色。Servers中左边一个是Proposer,另外两个和自己充当acceptor,更像我们真实的系统。实际上,Raft和ZAB协议基本相同。两者差别很小,就是心跳的方向不同。Raft和ZABRaft和ZAB协议将MultiPaxos分为三个子问题:这里不多说。另外,raft官网可以自行操作模拟选举过程。小结今天我们从CAP谈起Raft和ZAB,穿插着各种名词,不管模型怎么变,我们始终只有一个目的,就是如何在容错的分布式架构下保证整个系统的可用性以及一致性。最理想的模型当然是Paxos,但是理论和实现还是有差距的,于是就诞生了Raft和ZAB。虽然只有一个leader,但是我们允许leader挂掉,重新选举leader。妥协。
