本文继续研讨paxos算法。目前本人读到了paxos协议的实现部分,相对来说还是比较好理解的。当然,应用容易与否我们以后再进行深入探讨。

我们由前文知道了paxos算法的三大基本定理,并且可以知道,只要投票(法案)满足这三个定理,在不考虑时间的情况下,一定会具有一致的结果。 但是,怎么样的过程是可以满足的呢?

初始协议

$B_{1}(\beta)$的条件

首先,针对$B_1(\beta)$,我们知道需要满足任意两个投票都得具有不同的序号。 这个问题不难解决。 对于每一个priest(牧师),只需要有一个账本,记录下他曾经用过的序号,选择新的,就一定可以保证不重复。 对于多个牧师之间防止冲突,就是每个人都有一个序列集合,他们只从自己的序列集合里面取值,这样可以保证不会冲突。 根据lamport所说,虽然Paxon并没有给我们说怎么解决的,但是有一个很轻松的解决办法。就是创建一个字典集,例如(13,$\alpha$)<(13,$\beta$)<(15,\alpha)。先按序号排序,如果序号相同,就再按名称排序。这个地方的每个人的序列集合就是指字典集合哟!

$B_{2}(\beta)$的条件

对于定理$B{2}(\beta)$,我们知道是要求两次参与投票的$B{qrm}$和$B^{'}{qrm}$有交集,就是说,任意两次投票都会有同一个人参与进来了。 这一点是什么含义呢?从我们直观来想,就是每次投票人数都得大于一半的人。 比如一共10个人,第一次3个人参与,第二次4个人参与,那么一定会有3个人可以没参加,就一定存在一种可能,这两次参与投票的没有共同的人。 当然,Paxon人也有其他的定义方式,就是用权重。当权重大于一半的时候,就认定满足了集合。每个人的权重是按照出席率(参与投票次数)进行定义的。 为了保证这一点,在创建投票的时候,就得保证$B{qrm}$一定是一个大多数集合。

$B_{3}(\beta)$的条件

我们都知道,这点是最复杂的,表达起来也是最费劲的。我也尽力的描述下lamport大神的意思吧。 我们知道,针对$B{3}(\beta)$,需要使得本次投票序号$b=MaxVote(b,q,\beta)$。不难理解,这次的投票在创建的时候,我们要首先查询出$B{qrm}$的集合里面最大的$MaxVote(b,q,\beta)$. 但是具体的流程我们需要详细规定一下。

第一步

牧师p(我总是不由自主的想成法师)提出一个序号为b的法案,给一个牧师集合发送个指令$NextBallot(b)$,说明他下一个要生成的法案序号。

第二步

牧师q收到了p发送的指令,就查看下他参与的已投票法案中,最接近b的法案,然后$LastVote(b,v)$返回回去。当然如果它之前没有参与过投票,很简单,直接返回$nullp$即可。如果q已经参与过比b更大的法案投票呢?那也不行,它依然要找到比b要小的法案发回去。 所以,q需要一个笔记,记录下,它所有参与投票的法案。 当然了,我们在执行这一步,也是为了保证定理3的正确,所以一旦q返回了$LastVote(b,v)$,那么,在这个$LastVote(b),b{bal}$与b之间,就不能变更新的法案了,要不然,定理三一定会被破坏了。 这样,q得需要记录下这个信息,$[b_{bal},b]$之间不能再有新的法案。

第三步

p收到了q的回信,然后他就按照定理三选择最接近b的法案,组成一个v发送出去。指令是$BeginBallot(b,d)$。因为会有很多接收人,所以d就是满足定理3的法案,最接近b的。

第四步

q收到了p发来的法案$BeginBallot(b,d)$,如果他给其他人发送过$Last(b^{'},v^{'})$,与这个相冲突,那么拒绝使用这个法案。如果可以写入的话,那么就写入并回复$Voted(b,q)$。当然,这个也得记录下来。

第五步

如果p收到了所有q回复的$voted$信息,满足条件$B{qrm} \subseteq B{vot}$的话,就认为全票通过了,记录在案。并且,回复给每一个牧师一个$Success(d)$的信息。

第六步

很简单,如果q收到了$success(d)$的信息,也记录下来作为通过的法案。 注意,这每一步都是可选可不选的,因为即使不执行,最多会让速度降下来,并不会破坏最终的一致性。 但是,我们可以发现,这个很占据空间,要记录非常多的内容,而且效率也不高。 基本协议以及完整协议再开一篇新的博文吧。要不然太多了。