Q:处理器、进程或者节点各自独立,如何才能够达成共识?
一般情况下,节点间可以彼此传递消息达成一致。但是有故障节点存在的是时候,故障节点可能会向其他节点发送一个错误值,或者发送一些随即值,甚至不发送,导致每个处理器获取到不同的数据,最终计算出不一致的结果。
比如,处理器间的时钟同步,集群服务器间的数据同步 |
Reaching Agreement in the Presence of Faults 论文作者提出一种方法来消除错误处理器的影响 - 通过使用循环多轮的信息交换方案来处理;这样的方案可能会迫使有错误的处理器暴露自己有错误,或者至少使其行为与没有错误的处理器保持一致,从而使后者能够达成一致(当然,是在一定的条件下)。
Assumptions
假设总共有n个独立节点,其中错误节点m个,并且不知道具体是哪些节点出现了问题。节点之间只能双方彼此通信,并且假设数据传输是有保障的并且无延迟。接收方可以识别消息的发出者。
每个节点n具有私有值Vn(可以理解为当前该节点的状态,比如负载等)。对于给定的m、n,通过彼此间的信息交换,让每个节点持有一个所有节点私有值的向量。最终达成:
- 非故障节点能够计算得到完全相同的向量;
- 该向量中,非错误节点的所对应的元素元素,是该节点的私有值
举个例子:

交互一致性
虽然我们不需要最终知道哪些节点是有问题的,与错误节点对应的向量元素也可以是任意的;但是正确节点对于错误节点的向量元素必须是一致的。
比如下面的这种情况是不被接受的:

正确节点对所有节点(包括有故障的节点)持有的值达成共识,最终得到(交互式)一致性向量。这样,每个节点就能够通过对该向量的计算,继续得到业务上的所需要的值。
单节点错误
n=4, m=1
首先可以假设 n=4, m=1。进行两轮信息交换:
- 各个节点先把自己的私有值发给其他节点
- 各个节点彼此交换第一轮收到的信息
在信息交换过程中,错误节点可能会发出错误的值,或者不发出任何值,来干扰其他正常节点的计算。对于一个正常节点,如果没有收到节点N的消息,会将其置为默认值(假设为NULL)。
STEP1:

STEP2:

在两轮信息交换完成后,每个节点都会持有“一组”向量值元素。节点可以选取“多数”作为认可的元素值,形成最终的向量。

多节点错误
仅仅两轮信息交换不足以达成共识:
STEP1:

STEP2:

Finally:

继续下一轮交换信息…
m+1 轮后:
定义:
1)w=p1p2p3…pr, σ(w) 意为 pr -> p(r-1) -> p(r-2) -> ··· -> p2 -> p1,Vpr最终流转到p1的结果。
2)对于一个单节点,σ§ = Vp
3)如果一个节点q是正常的,那么他一定满足:对于任意的集合组成的字串w和任意节点p,
那么,通过如下方法帮助p节点得到q值(总节点n,错误节点m,n>=3m+1):
- 对于集合P的某个大小超过(n+m)/2的子集Q,σp(pwq) = v 对于每个长度不大于m的字串w(取自Q)都成立,那么p记录下v;
- 否则,算法将递归应用m-1,n-1,使P-{q}来替代P,并且对于每个长度不大于m的字串w(取自于P-{q})
step1:(目的是确定源节点q正确与否)一定能够找到一个全部是正常节点的集合Q(size <= m),使得正常的源节点q的值,经过Q处理后,依然不变。

step2:(目的是对错误节点的值达成共识)如果源节点q没能满足step1,说明q在乱发值,q是一个问题节点。
q向d发送X:

q向e发送Y:

所以q的值是多少不重要了,重要的是其他节点要对q的值达成共识。做法,把问题节点q踢出去,询问其他节点,在他们眼里,q是多少。如果某个值Vq’超过半数认可,那么就以Vq’作为q的值,否则,记默认值NIL。即:
p 问q’(中间也经过了step1的处理),你眼里q是多少?如果获得了不一致的答案,说明q’也有问题,踢了,再问其他节点,最终得到一个正常节点认可的值Vq’1
最终,p得到了其他所有正常节点眼里的q值: Vq’1 Vq’2 … Vq’k,如果在这中间,某个值Vq’m超过了半数,那么以Vq’m作为q的值,否值取默认值NIL。
这个过程就像是询问“认可值”,只要获得了足够多的“认可”,就可视Vq为q的值。
n=7, m=2
以A为主视角
step1: 每个节点把自己的值发送给其他节点

step2: 每个节点分享上一轮接收到的值
step3: 每个节点再次分享上一轮接收到的值

- 对于一个正常节点,经过子集Q,抵达A的值不会变

- 对于一个非正常节点,经过子集Q,抵达A的值可能会变。此时需要踢出错误节点,来达成值的一致


拜占庭国王放下手中的 Reaching_agreement_in_the_presence_of_faults.pdf,陷入沉思。

最近他的军队正在攻打敌方同样强大的城池,需要将领们协同一致才可制胜。而他也知道,将军们中间有叛徒,正因此进攻才耽搁许久。忽然他眉头一皱,计上心来!

国王究竟想到了什么办法呢?请看下回:

回想一下,上一节给出的过程需要两轮信息交换,第一轮“我的私有值是”,第二轮“节点x告诉我他的私有值是....”。在m个节点故障的一般情况下,需要m + 1轮通信。为了描述该算法,可以以更通用的方式描述这种消息交换。 |