本文是看了知乎上面一位牛人的回答有感而发。现在将原文地址链接如下:https://www.zhihu.com/question/19787937
首先我们需要了解什么是paxos算法:paxos算法是一种分布式一致性算法,主要任务是为了解决分布式中的一致性问题,那么什么是分布式中的一致性问题,可以看看上一篇博客:分布式事务中的算法策略
概念介绍:
A. 法定集合: 法定集合就是指的超过一半数目的集合就称为法定集合。这里引出法定集合是由于法定集合的概念是paxos算法的基础---任意两个法定集合中必定有一个公共元素。
B. 相互平等: (后面会提到)就是每一个进程都有权利进行值的设定。不存在有上帝进程。
C. 活性: 分布式一致性算法总能达到一致称为活性。
举例场景: 存在进程p1-p3,变量v,使用paxos算法来使得所有进程都对v达到一致。
决定条件: 就是什么情况下达到一致,当法定集合中的元素决定了他们共同的v值时达到一致。
安全保证: 如果法定集合已经决定了v值,那么v的值将不能变化。
论证条件:
A。接受多值: 就是说每一个进程必须能够接受多个值,原因: 假设一个进程只能接受一个值,那么如果每个进程都给自己的v设了不同的值,那么根据条件分布式不能达到一致。违背了活性的要求。
B. 安全性: 如果p1,p2都设置了自己的v值为c,那么根据判断条件我们可以知道现在已经达到了一致(法定集合已经确定了v值),那么现在p3进程设定了v=d,并设定p2的v=d,那么根据条件又达到了一致性,这显然是不符合安全保证的(法定集合的v值不能变化)。
C. 学会拒绝: 出于活性的考虑,我们不能只接受一个值,每一个进城都要能够接受多值。那么就势必会导致安全性问题。所以需要节点学会拒绝,就是当法定集合中的v值已经被决定为c之后,当p3再想设置p2的v值的时候,p2就应该拒绝这个要求。同时可以得出一个结论: 如果法定集合决定了v的值那么其他节点将没有权利对自己的v值进行设定,而是只能设定为c。
D: 无权选择: 根据上面的论证,我们得知,存在一些节点没有权利设置自己的v值,那么我们如何决定这些节点(假设为pi)的v值,pi又如何得知现在法定集合决定的v值呢?
方案一: 进程之间相互通信告知自己现在的v值,那样pi就可以根据一致性判断条件来决定哪一个v值是被法定集合决定的了。但是这个方案并部可行,原因是如果判断的过程中p1进程挂了,只有p2和pi存活,那么如何选择现在的值?强行默认为一个值K,那样的话不满足安全性问题。如果只是继续等待不满足活性问题。
方案二:如何选值: 现在法定集合Q1已经决定了v值为c,那么pi进程随机组成一个法定集合Q2,那么Q1和Q2中必然存在一个公共节点pj,我们现在所需要做的就是让pi的v为Q2中pj和值还是其他节点pn的值。
E: 如何拒绝: 上面的论证抛出了一个问题,就是方案二中的pi如何选值的问题:存在这种情况: 当pi询问法定集合Q2的各个进程时,得到的回答都是我们尚未决定v值,那么可以得出现在整个分布式还未达到一致,那么现在pi将能够有权限决定自己的值是多少。那么问题来了,如果同时有两个节点pi,pj都获得了决定自己值的权限,那么将会出现这种情况Q2和pj所在法定集合Q3存在共同节点pn,pi和pj会同时对pn赋值。为了安全性考虑,我们需要pn能够决定拒绝哪一个值。
F: 上面的论证留下的两个问题:如何选值,如何拒绝。为了描述清晰,我们提出两个概念: 提议者,接受者。提议者负责如何选值,接受者负责如何拒绝。提议者首先向接受者进行询问,得到一个法定集合的进程恢复,如果已经决定了v的值,那么只用设定v的值即可,如果没有决定那么有权设定v=c。此时不妨让接受者负责写入v的值。提议者尝试令接受者写入自身v的值的过程叫做提议。这个过程中提议者发送给接受者的消息称之为提案,显然提案包括自身的v值。
那么提议者向接受者发出提议会导致安全性问题,接下来就是如何拒绝的问题了。
针对上面认证过程中的如何决定情况,我们应该如何选择一个v来拒绝呢?我们提出一种方法,就是在每个提案中添加一个字段proposer-id来表示现在提案的id,由接受者来决定选择哪一个提案。不防设选择proposer_id大的来选择。但是出现一个问题,如果现发送过来的提案的proposer-id是小的,那么会导致pn两次接受提案,显然不合理。解决办法是,给pn设置一个初始值,如何设置这个值呢?设置哪一个值比较合理。其实这里需要有一个预提案的过程,在这个预提案过程中我们将设置pn的初始值为提案中较大的一个。并且再接受提案的过程中忽略提案id小于pn初值的提案。
待续: