2019独角兽企业重金招聘Python工程师标准>>>
一、前言
分布式多副本一致性在现实应用中是非常重要的,它既可以保证数据节点无单点(HA)时还能保证数据节点的一致性。此类协议比较著名的有paxos、raft和zab(zookeeper实现)等。其中,paxos允许多点写,而raft则是会先选举出一个leader,所有的写都会通过leader完成。
本文会先介绍paxos思想,以后还会介绍raft。关于paxos的文章已经很多了,而且讲解的风格和方式不尽相同。我发现,如果单纯从纯理论角度来分析paxos,虽然在论证上会严谨一些,但是也导致即使你写了很大的篇幅,最终还是达不到想要的效果,最终还是:晦涩难懂。这其实也是paxos和raft的另一个区别,相对而言,raft从理论上就比paxos简单易懂的多。
本文不准备从理论角度剖析paxos算法原理,我会尝试使用图形(伪代码)的方式给让大家对paxos有一个宏观的把握,同时,我在阅读了很多paxos文章之后,发现一篇以现实场景为角度讲解paxos的文章,我将其稍微修改了一下引用在这里。我相信,通过这两种角度,你的脑海中应该觉得paxos不再神秘。
二、paxos概念
首先来必须看一下Lamport对paxos算法的文字版描述。
阶段一:
1、Proposer选择一个提案编号为Mn,然后向Acceptor的某个超过半数的子集成员发送编号为Mn的Prepare请求。
2、如果一个Acceptor收到一个编号为Mn的Prepare请求,且编号Mn大于该Acceptor已经响应的Prepare请求的编号,那么它就会将已经批准(accept)的最大编号的提案作为响应反馈给Proposer,同时该Acceptor会承诺不会再批准(accept)任何编号小于Mn的提案。
阶段二:
1、如果Proposer收到来自半数以上的Acceptor对其发出的编号为Mn的Prepare请求的响应,那么它就会发出一个针对[Mn,Vn]提案的Accept请求给Acceptor。注意:Vn的值就是收到的Prepare响应中编号最大的提案的值,如果响应中不包含任何提案,那么它就是任意值。
2、如果Acceptor收到这个针对[Mn,Vn]提案的Accept请求,只要改Acceptor尚未对编号大于Mn的Prepare请求作出响应,它就可以通过这个提案。
注意:
Acceptor是一个集合(即不止一个Acceptor)。之所以要过半,是因为,任意的过半的集合都至少会有一个公共的交集,这适用于分区脑裂等场景。
是的,以上就是paxos算法的完整描述,是不是觉得非常“简单”,但是细细思考起来又会觉得比较抽象?下面我把上面的文字整理成图形伪代码的方式:
raft vs multi-paxos
- raft仅允许日志最多的节点当选为leader,而multi-paxos允许任意节点都可以当选leader。
-
multi-paxos则允许日志出现空洞,而raft为了比较的方便和便于拉平两个节点的日志,不允许日志出现空洞。
multi-paxos的leader只是知道最大的log index是多少,但是空洞部分,可以异步填充,而raft的leader,不但知道最大的log index是多少,也必须拥有从0到log index直接的之间日志,在被选择为leader后,raft的leader可以单向的向其他follower节点同步落后的日志,log只会从leader到follower单向同步
3.由于raft不允许日志的空洞,因此方便了比较和拉平两个节点的日志,同时,这种连续确认更大的一个优势是新的leader上任过程更简单了,而Multi Paxos的新leader上任过程很复杂。
paxos中一开始没有包含全部已提交的条目的节点也可以被选为leader,在当选为leader后需要有一些另外的机制来保证找到丢失的条目,这种方式大大增加了复杂性。而Raft协议的选举过程中,日志落后的候选节点无法被选中为Leader,这大大减小了选举和日志复制的相关性,简化了raft的算法理解难度。
转载于:https://my.oschina.net/fileoptions/blog/883282