目录
0-前言
1-导引
2-不可能性
3将军(1叛徒)问题不存在解/不能达成共识
少于3m+1个将军(有m个叛徒)不存在解/不能达成共识
精确一致性与近似一致性是同等困难的
3-使用口头消息的解
“口头消息”的含义
OM(m)算法的步骤
OM(m)算法的正确性推导
4-使用签名消息情况下的解
“签名消息”的含义
SM(m)算法的步骤
SM(m)算法的正确性推导
5-通信路径缺失
6-可靠性系统
可靠性系统的要素
消息传递系统的约束
7-小结
8-参考文献
-
0-前言
- 下面部分摘自Lamport的my writings,my writings是Lamport本人对自己以往发表的论文的一些总结,其中很多文字涉及到这些论文的创作来源
- 从下面的文字可以看出,该论文的内容实际上已发表在1980年的Reaching Agreement in the Presence of Faults>>中,只是引入了拜占庭将军这一说法,同时增加了一些新的内容
- 我一直觉得正是因为通过用一组围坐在圆桌旁的哲学家来表述,Dijkstra 的哲学家就餐问题才变得如此让人关注(比如在理论界,它可能比读者/写者问题都引人注目,尽管读者/写者问题可能更具实际意义),我认为Reaching Agreement in the Presence of Faults>>所描述的问题十分重要,值得计算机科学家们去关注
- 哲学家就餐问题使我认识到,把问题以讲故事的形式表达出来更能引起人们的关注
- 在分布式计算领域有一个被称作中国将军问题的问题
- 在这个问题中,两个将军必须在进攻还是撤退上达成一致,但是相互只能通过信使传送消息,而且这个信使可能永远都无法到达
- 我借用了这里的将军的叫法,并把它扩展成一组将军,同时这些将军中有的是叛徒,他们需要达成一致的决定
- 同时我想给这些将军赋予一个国家,同时不能得罪任何读者
- 那时候,阿尔巴尼亚还是一个完全封闭的国家,所以我觉得应该不会有阿尔巴尼亚人看到这篇文章,所以最初的时候这篇论文题目实际是The Albanian Generals Problem
- 但是Jack Goldberg后来提醒我在这个世界上阿尔巴尼亚之外还有很多阿尔巴尼亚移民,所以建议我换个名字
- 于是就想到了这个更合适的Byzantine generals的叫法
- 写这篇论文的主要目的是将Byzantine generals这个叫法用在这个问题上
- 但是一篇新的论文需要有新的想法,于是提出了一种描述通用的3n+1处理单元的算法简单方式(Shostak的4处理单元算法很精妙而且容易理解,但是Pease的通用化扩展算法却不那么好懂)
- 同时我们将网络扩展到非全互联网络的情况,而且增加了一些实现相关的细节
- 一个可靠的计算机系统必须处理有故障的组件,这些组件可能引入与系统其它部分相冲突的信息
- 这样的场景可以用一组指挥军队围困敌国城市的拜占庭将军来描述
- 将军之间只能通过信使传递信息,他们必须在相同的作战方案上达成一致
- 但是,他们之中可能存在叛徒,这些叛变的将军会竭力的扰乱其它人
- 拜占庭将军问题,就是指找到一种算法可以保证那些忠诚的将军可以达成一致
- 结果表明,如果使用口头信息,当且仅当超过三分之二的将军是忠诚的时候该问题才可解,也就是说一个将军可以扰乱两个将军
- 如果使用不可伪造的书面信息,对于任何数目的将军和叛徒,该问题都是可解的
- 此外,本文还讨论了如何将该问题的解应用于可靠的计算机系统实现中
-
1-导引
- 一个可靠的计算机系统必须能够处理一个或多个的组件的失败
- 一个失败的组件可能会表现出一种经常被忽略的行为:向系统的其他部分发送相矛盾的信息
- 可以将处理这种失败的情况的问题抽象出来,就是这里的拜占庭将军问题
- 在论文的绝大部分内容都是讨论这个抽象后的问题,只是在末尾会讨论如何将该问题的解应用在可靠计算机系统的实现中
- 假设有几股拜占庭军队现在正在一个敌城外扎营,每股军队由一个将军指挥
- 将军之间只能通过信使通信
- 观察完敌情后,他们必须达成一个相同的行动计划
- 然而,有些将军可能是叛徒,他们会尽力阻止那些忠诚的将军达成一致
- 将军们必须有一个算法来保证如下条件:
- A-所有忠诚的将军必须达成相同的行动计划
- 忠诚的将军将会做该算法要求他们做的事情,但是叛变的将军可以做任何他们想做的事情
- 无论叛变的将军会做什么,算法必须要保证条件A
- 诚实的将军不能仅仅达成一致,他们还应该达成一个合理的行动计划
- 也就是说,实际上我们想保证:
- B-当只有少数人是叛徒的时候,他们不能导致那些诚实的将军们采纳一个糟糕的计划
- 条件B很难去形式化,因为它需要精确的定义何谓糟糕的计划,当然我们也并不尝试去给出这样的一个定义
- 我们来考虑将军们如何做出决定,每个将军都会观察敌情,并将他的观察结果告诉其他将军
- 假设v(i)代表第i个将军发送的信息
- 每个将军使用某种方法来根据这些信息v(1),v(2)……v(n)来拟定作战计划(n代表将军的总数)
- 通过让所有的将军使用同一种方法就可以满足条件A,通过使用一种健壮的方法条件B也可以满足
- 比如,现在需要决定是进攻还是撤退,v(i)代表第i个将军关于进攻还是撤退的意见,最终的决定可以通过在他们之间进行一个多数决的投票来决定
- 在这种情况下,只有当持两种意见的忠诚将军数目几乎相同时,少数的叛变将军才能影响最终的结果
- 但是这种情况下,无论是进攻还是撤退都算不上是糟糕的方案(这就说明满足条件B)
- 虽然这种策略可能不是满足条件A和B的唯一一种方式,但是目前我们仅想到这一个
- 该方法假设存在一种方法,将军们可以相互传递各自的v(i)值
- 很明显的一种方法是,将军i,让他的信使将v(i)送给所有的将军
- 但是,这样行不通,因为如果要满足条件A,需要每个忠诚的将军收到相同的v(1),v(2)……v(n),但是一个叛变的将军可能会给不同的将军发送不同的值
- 对于条件A来说,如果要满足,下面的条件必须成立:
- 1-每个忠诚的将军必须收到相同的v(1),v(2)……v(n)
- 条件1暗示一个将军并没有必要使用一个直接从第i个将军那收到的v(i)值,因为一个叛变的第i将军可能给不同的将军发送不同的v(i)值
- 但是这样意味着,满足条件1的同时,很可能一不小心就使用了一个与第i将军发送的v(i)不同的值,即使第i个将军是诚实的(因为我们可能采用了从其他将军处得来的关于v(i)的值,但是这个将军可能是叛变者,它可能自己已经改变了v(i)的值,这样即使第i将军是诚实的,但是经过叛变者之后它的值也已不再受控了)
- 但是为了满足条件B,我们绝不允许这种情况发生
- 比如我们,我们不能允许少数的叛变者就使得忠诚的将军们在一个个”retreat”, “retreat”…… “retreat”,中做决定,而每个忠诚的将军发送的明明是”attack”
- 因此,我们还要为每个i增加如下的需求
- 2-如果第i个将军是忠诚的,那么其他的忠诚的将军必须使用他发送的值作为v(i)的值
- 我们可以改写条件1,使得它是针对任意i的条件(无论第i个将军是否是忠诚的):
- 1’-任意两个忠诚的将军使用相同的v(i)值
- 条件1’和2现在都是针对第i个将军的值v(i)的了
- 因此,我们可以只考虑一个将军如何发送他的值给其他人
- 现在我们用一个发令将军向它的下属发送命令的形式来重新描述这个问题,就得到如下问题:
- 拜占庭将军问题
- 一个发令将军向他的n-1个下属将军发送命令,使得:
- IC1-所有忠诚的下属都遵守相同的命令
- IC2-如果发令将军是忠诚的,那么每个忠诚的下属必须遵守他发出的命令
- 条件IC1和IC2被称为交互一致性(interactive consistency)条件
- 可以看到,当发令将军是忠诚的时候,IC1可以由IC2导出
- 然而,发令将军不一定是忠诚的
- 为了解决最初的问题,第i个将军只需要利用拜占庭将军问题的解法发送命令”使用v(i)作为我的值”,就可以将他的值v(i)发送给其他的将军
- 此时其他的将军就扮演拜占庭将军问题中的下属的角色
- 1-每个忠诚的将军必须收到相同的v(1),v(2)……v(n)
- A-所有忠诚的将军必须达成相同的行动计划
-
2-不可能性
- 拜占庭将军问题看似很简单
- 它的难解之处是通过一个令人惊讶的事实而体现出来的:
- 如果将军们只能发送口头消息,除非有超过三分之二的将军是忠诚的,否则该问题无解
- 尤其是,如果只有三个将军,其中一个是叛变者,那么此时无解
- 口头消息是指信息的内容完全在发送者控制之下,这样一个叛变了的发送者可能会传送任何可能的消息
- 正常情况下计算机之间传输的消息就属于这种类型
- 在第4节,会考虑带签名的书面消息类型,对于这种类型该结论不成立
-
3将军(1叛徒)问题不存在解/不能达成共识
- 现在来说明为什么使用口头消息,当三个将军中有一个叛变时是无解的
- 为了简单起见,我们只考虑是”进攻”还是”撤退”这一简单的决定的情况
- 首先看图1里的情形,发令者是忠诚的并且给下属 1,2 发送了一个”进攻”命令
- 但是下属2是个叛变者,他对下属1说,他收到了一个”撤退”命令
- 如果要保证IC2满足,下属1必须遵守命令去进攻
- 现在考虑图2所展示的另一种情形,发令者是一个叛变的将军,发送了一个“进攻”命令给下属1,但是给2发送的是“撤退”命令
- 下属 2 转告下属 1 说他收到的是“撤退”命令
- 下属1,不知道谁是叛变者,同时他也无法判断发令者发送给下属2的真实的命令到底是什么
- 因此,这两幅图中的情形,对于1来说是完全相同的(他不知道谁是叛变者,两种情况下他都是只知道发令者告诉他要进攻,但是2说发令者说要撤退;所以他无法区分出这两种情形,但是如果是情形1,他必须进攻,如果是情形2他如果也进攻,那就是说无论如何他都听发令者的命令,如果选定了这1算法,因为1,2本质上是等价的角色,那么2也需要采纳该算法(即使下属 1 告诉他发令将军说的是“进攻”,他也必须服从自己收到的命令),这样2就会选择撤退,这就违发了IC1;如果他要选择是否撤退,那么意味着他要区分这两种情况,但是实际它是无法区分的,因此无解)
- 如果叛变者总是在说谎的话,对于1来说就无法区分这两种情况,因此他就必须选择遵守进攻命令,因此无论何时,下属1从发令者那收到进攻命令,他都必须遵守它
- 然而,类似的结论也指出(进攻与撤退不过是两个称谓,将2者互换一下就可以得出结论),如果下属2从发令者那收到了撤退命令,他都必须要遵守,即使1告诉他发令者的命令是进攻
- 因此对于图2的情形来说,2必须遵守撤退命令,而1必须遵守进攻命令,因此违法了条件IC1
- 因此三个将军中有一个是叛变者时,该问题无解
-
少于3m+1个将军(有m个叛徒)不存在解/不能达成共识
- 精确一致性的证明:
- 利用这个结论,我们可以说明当有m个叛徒,而将军数小于3m+1时,该问题无解
- 证明(反证法):
- 将3m将军m叛徒问题中的将军称为阿尔巴尼亚将军,3将军1叛徒中的将军称为拜占庭将军,以示区分
- 注意此处的拜占庭将军并不单指叛徒,而是指所有的将军
- 拜占庭指挥官代表一个阿尔巴尼亚指挥官和m-1个阿尔巴尼亚中尉,两个拜占庭中尉分别代表m个阿尔巴尼亚中尉
- 因此对于拜占庭叛徒将军(代表m个阿尔巴尼亚将军),最多对应m个阿尔巴尼亚叛徒将军
- 由IC1可知,m个阿尔巴尼亚中尉(由单个诚实拜占庭中尉所代表)遵循相同的命令,这一命令也是该诚实拜占庭节点所需要遵守的命令
- 对于阿尔巴尼亚将军,可知是满足IC1和IC2的,又由以上对应关系,可知3将军问题是满足IC1和IC2的,也即3将军问题存在解
- 这与已知(3将军(1叛徒)问题不存在解)矛盾,故3m将军问题不存在解
-
精确一致性与近似一致性是同等困难的
- 可能有人认为解决拜占庭将军问题的难点在于它要求达到精确的一致
- 下面我们通过证明近似一致实际与精确一致一样困难来说明情况并不是这样
- 近似一致性的证明:
- 我们现在假设不是要达到一个精确的战斗计划,将军们只需要达成近似的进攻时间
- 详细来说,我们假设发令者需要确定进攻时间,同时需要满足如下两个条件:
- IC1’-所有的忠诚的下属相互之间在10分钟内发起进攻
- IC2’-如果发令将军是忠诚的,所有的忠诚的下属在发令者给定的命令时间点的10分钟之内发起进攻
- (我们假设命令是在进攻的前一天下达并被处理的,而且与命令的接收时间无关,只需要关注命令中给定的进攻时间)
- 类似于拜占庭将军问题,这个问题只有在超过三分之二的将军是忠诚的时候才有解
- 我们通过表明这样的一个事实来证明它:如果存在这个问题的一个三将军解,我们可以通过这个解构造出拜占庭将军问题的一个三将军解
- 证明(依旧反证法):
- 假设发令者希望发送一个进攻或者撤退命令
- 他会使用假设的那个算法,通过发送一个在1:00进行攻击的命令来作为进攻命令,通过发送在2:00进行攻击的命令作为撤退命令
- 每个下属使用下面的过程来获取命令:
- (1)每个下属根据收到的攻击时间而遵循的命令:
- 时间是1:10以前,则攻击
- 时间是1:50之后,则撤退
- 否则转向(2)
- (2)查询其他下属做出的“进攻”或“撤退”的命令:
- 如果其他中尉做出了决定,则该中尉遵循与其他中尉相同的命令
- 否则,撤退
- (1)每个下属根据收到的攻击时间而遵循的命令:
- 根据IC2’如果发令者是忠诚的,那么一个忠诚的下属会在第一步里获取正确的命令,这样IC2就满足了
- 如果发令者是忠诚的,IC1可以由IC2导出
- 因此只需要证明当发令者是叛徒时的IC1成立即可
- 因为最多有一个叛徒,意味着两个下属都是忠诚的
- 根据IC1’,如果一个下属在步骤(1)里决定进攻,那么另一个就不能在步骤(1)决定撤退,因此要么他们在步骤(1)里都达到了相同的决定,要么至少其中一个将其决定推迟到了步骤(2)
- 为什么会进入步骤2呢?
- 因为当发令者是叛徒时,两个忠诚的下属达成的时间虽然相差在10分钟内但可能是随意的,比如可能在1:10-1:50之间,所以最后有可能两个都没有在第(1)阶段得出决定,而最后都选择撤退
- 在这种情况下,很容易看出他们都达到了相同的决定,因此IC1满足
- 这样我们就构造出了对于存在一个叛徒的拜占庭将军问题的三将军解,而这是不可能的
- 同理,拜占庭的3将军问题不存在解,因此本问题也不存在解
- 同理对于该近似一致性的3m将军问题的解与上文所述一致
-
3-使用口头消息的解
- 前面我们指出,使用口头消息时对于一个含有m个叛徒的拜占庭将军问题,至少有3m+1个将军才可解
- 现在我们给出一个针对3m+1或更多将军的情况下的解
- 但是,首先我们需要明确“口头消息”的含义
-
“口头消息”的含义
- 每个将军都会执行某个算法来把消息传送给其他将军,同时我们假设忠诚的将军会正确地执行该算法
- “口头消息”可以通过如下我们为将军消息系统所做的假设来具体定义:
- A1-每个发送的消息都会被正确的传输
- A2-消息的接收者知道发送者是谁
- A3-消息如果丢失可以被检测到
- 假设A1和A2是防止叛徒介入其他两个将军的通信中
- 根据A1,他无法妨碍其他两位将军发送的消息
- 根据A2,他不能伪造消息来搅乱其他两位将军的交流
- 假设A3是为了防止一个叛徒通过简单的不发送消息来阻止一次决定
- 这些假设在实际中的实现将会在第6节进行讨论
-
OM(m)算法的步骤
- 本节以及下一节的算法,要求每个将军都能够直接向其他将军发送消息
- 在第5节我们会描述没有该条件限制下的算法
- 一个叛变的发令者可能会决定不发送任何命令
- 由于下属们必须遵守相同的命令,因此这种情况下他们必须有一个默认的命令
- 我们使用RETREAT(retreat,撤退)作为该默认命令
- 我们归纳性的定义该口头消息(Oral Message简称OM)算法OM(m),m是非负整数,m为叛徒个数,通过这个算法,一个发令者向n-1个下属发送命令
- 可以证明对于3m+1或者更多个将军时,OM(m)解决了拜占庭将军问题
- 用”获取一个值”来取代”遵守一个命令”这样的说法在描述该算法时显得更方便一些
- 算法中还假设了一个函数 majority(取收到的消息(v1,v2……vn-1)的大多数(大多数的确定:众数或者中位数)),当一系列元素(v1,v2…vn-1)中出现次数占半数以上的元素为v时,则 majority(v1,v2…vn-1) = v,否则 majority(v1,v2…vn-1) = RETREAT
- 用发送/接收某个值来代替发送/接收命令
- 算法OM(0)
- (1)发令者发送他的值给每个下属
- (2)每个下属使用他从发令者那收到的值,如果没有收到则使用值RETREAT
- 算法OM(m)m>0
- (1)发令者发送他的值给每个下属
- (2)对于任意i,vi代表下属i从发令者处收到的值,如果没有收到则采用RETREAT;下属i扮演算法OM(m-1)中的发令者,并采用该算法将值vi发送给其余的n-2个下属
- (3)对于任意i以及任意的j!=i,让vj代表下属i在步骤2中(使用算法OM(m-1))从下属j处收到的值,如果他没有收到这样的值,就采用RETREAT;下属i采用函数majority(v1,v2…vn-1)的值
- 算法OM(m)中的 m 指代算法最多可以容许有多少个叛徒
- 不是要求有 m 个叛徒,或者已知 m 个叛徒
- OM(0)即为不提防任何叛徒的情况
- 在 m > 0 的情况下,每个下属都无法信任任何人,因此对于每个接收到的值,他们都需要使用 majority(v1,v2…vn-1) 确定
- 在第 m 轮中,发令将军给每个下属都发送了一个值,但谁都不敢相信这个值
- 因此每个下属都给其他 n-2(除消息上游和自己)个下属发送自己接收到的信息以帮助他人做决定(叛徒可以发送任何值,但规定了遵守此规则),这就是 m-1 轮
- 而 m-1 轮收到的值大家又需要其他人的信息做决定,因此又给其他 n-3(除消息上游上上游和自己)个下属发送自己的信息帮助他人做决定
- 以此类推,一直到 OM(0) 为止
- 上面整个过程是一个递归的过程,每个下属都会给其他下属发送很多信息,为了使这些不同信息得以区分,每个下属可以在发送消息时加上自己所属序号的前缀
- 示例:
- 如图示例:m=1,n=4
- 当一个下属为叛徒的情况
- (1)在OM(1)的第一阶段,指挥官发送值v给其余三个下属
- (2)第二阶段:下属1用算法OM(0)发送值v给下属2,下属3发送给下属2值x
- (3)在第三步,下属2此时获得了两个v和一个x,因此最终下属2获得正确的值为v=majority(v,v,x),下属1同理
- 当指挥官为叛徒的情况
- (1)指挥官发送值x,y,z给下属1,2,3
- (2)~(3)最终每一个下属都得到majority(x,y,z),并不能得到统一的解
- 由以上过程,可知算法是递归运行的,从OM(m)到OM(m-1)…OM(0),OM(m)调用n-1个OM(m-1),每个OM(m-1)调用n-2个OM(m-2)…一直到OM(0)
- 节点数n,叛徒数m的情况下若叛徒节点参与通信(发送错误信息):
- OM(m-1)被调用的次数n-1
- OM(m-2)被调用的次数(n-1)(n-2)
- OM(m-3)被调用的次数(n-1)(n-2)(n-3)
- OM(m-k)被调用的次数(n-1)(n-2)(n-3)..(n-k)
- 总的次数:n-1+(n-1)(n-2)+(n-1)(n-2)(n-3)+(n-1)(n-2)(n-3)..(n-k)
-
OM(m)算法的正确性推导
- 为了证明算法OM(m)对于任意m的正确性,我们首先证明如下的辅助定理:
- 引理1:对任意m,k,若系统中将军总数超过2k+m,叛徒最多有k个,算法OM(m)满足IC2,即如果指挥官诚实,那么每一个诚实的下属都遵从指挥官的命令
- 引理1证明:
- 当m=0时,由A1可知,IC2满足
- 当m>0时,在OM(m)算法的step(1),指挥官把值传给n-1个下属,在step(2)中,每一个诚实的下属调用OM(m-1),前文已知n>2k+m,因此n-1>2k+(m-1),所以每一个诚实的下属i都会得到城实下属的vj=v
- 又因为n-1>2k+(m-1)>=2k,即这n-1个下属的半数以上都是诚实的,所以step(3)中获得的majority(v1,v2……vn-1)必等于v,即满足IC2
- 定理1:对任意m,如果将军数量大于3m且叛徒数最多是m,算法OM(m)满足IC1和IC2
- 定理1证明:
- 当不存在叛徒(m=0)的时候,显然OM(0)满足IC1&IC2的约束,因此假定OM(m-1)成立,证明OM(m),m>0成立
- 假设指挥官诚实,由引理1可知,若k与m相等,则OM(m)满足IC2,又因为在指挥官诚实的情况下IC1可以由IC2推出,所以只需要证明在指挥官是叛徒的情况下检验是否满足IC1
- 已知指挥官是叛徒,最多有m个叛徒
- 所以下属中最多有m-1个叛徒
- 下属的数量是3m-1,且3m-1>3(m-1),因此OM(m-1)满足IC1&IC2
- 对于每一个j,任意两个诚实的下属得到的都是相同的vj的值(这任意两个下属有一个是j的话就由IC2可以推出;若不包括j的话,由IC1可以推出)
- 因此,任意两个诚实的下属最终会得到相同的v1,v2……vn-1,也即算法step(3)的majority(v1,v2……vn-1)相同,OM(m)的IC1得以证明
- 对于证明的思路分析:
- 采用了归纳演绎法
- 显然OM(0)恒成立
- 假设OM(m-1)成立
- 若指挥官诚实,那么由引理1可推OM(m)的IC2成立,进而OM(m)IC1成立
- 若指挥官为叛徒,
- 通过归纳法证明过程中对任意j由OM(m-1)的IC2推出任意两个诚实下属有相同vj的值,
- 这是因为如果j为两个诚实下属之一,那么就符合OM(m-1)的IC2条件;
- 如果j不是这两个诚实下属之一,那么j是诚实将军自不必多说,
- 如果j是叛徒的话,因为该任意两个下属是诚实的,
- 由IC1也可推知二者Vj服务器托管网的值也相同,
- 虽然不是正确值,但达成了共识
- 因此满足IC1,即OM(m)满足IC1&IC2
- 综上,定理1成立
-
4-使用签名消息情况下的解
- 正是叛徒能够“撒谎”导致拜占庭将军问题变的难以解决
- 如果可以限制他们的这种能力,那么问题就会变得容易解决了
-
“签名消息”的含义
- 一种方法是允许将军发送不可伪造的签名消息
- 更准确的说,是我们给 A1-A3 加上如下的假设:
- A4
- (a)一个忠诚的将军的签名不可以被伪造,且他签署的消息的内容的任何改动都可以被检测到
- (b)任何人都可以验证某个将军签名的真实性
- A4
- 我们不对叛变将军的签名做限制
- 也即我们允许他的签名被另一个叛徒伪造,从而允许叛徒之间勾结
- 引入签名消息后,之前所说的限制就不存在了,对于任意叛徒的任意将军数都有可行解
-
SM(m)算法的步骤
- 算法大致流程:
- 指挥官发送带有自己签名的信息给所有下属
- 下属在指挥官签名的基础上附上自己的签名并发给其他下属
- 其他下属重复操作
- 定义choice函数将一组命令转变成单个命令:
- 1-如果集合V由单个元素v组成,choice(V)=v
- 2-choice(None)=RETREAT
- choice函数的定义也可以是中位数
- x:i表示被将军i签名的信息x,v:j:i表示先被j签名的信息v,然后又被i签名的v:j
- General 0代表指挥官
- 每一个下属 i 都维持一个集合Vi,Vi是当前收到的被正确签名的命令的集合(如果指挥官诚实,那么此集合只有一个元素)
- 算法SM(m)步骤:
- 首先将 Vi 集合初始化为空集
- (1)发令将军签署并发送他的值给每个下属
- (2)对于第 i 个下属:
- (A)如果他从发令将军处收到了 v:0 形式的消息,且他尚未接收过任何命令,则他将:
- 1. 设置 Vi 为 {v}
- 2. 发送 v:0:i 消息给所有其他下属
- (B)如果他收到形如 v:0:j1:…:jk 的消息,并且值 v 不在集合 Vi 中,则他将:
- 1. 将值 v 添加至 Vi
- 2. 如果 k
- (A)如果他从发令将军处收到了 v:0 形式的消息,且他尚未接收过任何命令,则他将:
- (3)对于第 i 个副将:当他不会再收到任何消息时,通过 choice(Vi) 选择出命令
- 在步骤(2),下属i会忽略任何已经包含在集合 Vi 中的命令v的信息
- 在步骤(3)如果一个下属不接受到信息该如何决断呢?
- 通过对k进行归纳法,容易得到对于任意的下属序列 j1,…,jk(k
- 一个下属在步骤(2)能够最多接收到一次 v:0:j1:…:jk:i 信息,若约束下属jk,要么发送该信息(指v:0:j1:…:jk:i),要么发送一条消息告诉其他人他不会再发送此类的消息,这样我们就可以判断是否所有消息都已经接收(由于 A3 限定,如果一个 jk 叛徒选择两种消息都不发送那也是可以检测到的)
- 除此以外,当无信息到达时超时机制也可用于进行决断(Section 6给出)
- 步骤(2)中收到签名的下属会丢弃具有不正确签名格式的信息,这是为了节省存储空间
- 因为如果不这么办的话,当一个命令 v 被 k 个下属签名并以消息形式传递给其他下属的时候,系统中就会存在(n−k−2)(n−k−3)…(n−m−2)个拷贝
- 以n=7,m=2为例:(本文应该是默认叛徒不参与通信(也可能是无法进行通信)或且发出的信息并不留存)
- 之后所有节点发现k=m,转步骤(3)
- 下图 5 展示了算法 SM(1) 在总共 3 个将军且发令将军是叛徒情况下的消息处理流程:
- 发令将军发送”进攻”命令给下属 1,发送”撤退”命令给下属 2
- 在第 2 步中,他们又把各自命令发送给对方
- 因此第 2 步之后 V1 = V2 = {“进攻”,”撤退”},下属 1,2 都遵循命令 choice({“进攻”,”撤退”})
- 这里可以观察到,不像之前图 2 中的场景,下属们可以知道发令将军是叛徒,因为他的签名出现在了两个不同命令当中,并且A4也能保证其结论的正确性
- 事实上,第m个将军并不需要继续在命令的后边附上自己的签名,因为他收到命令之后就不会再转发给别人了;因此SM(1)的签名是不必要的
- 算法大致流程:
-
SM(m)算法的正确性推导
- 定理2:对于任意的m,如果最多有m个叛徒,那么算法SM(m)解决了拜占庭将军问题
- 证明:
- 先证IC2,当指挥官是诚实的情况下,在步骤(1)他会发送v : 0给他的下属们,每一个诚实的下属在步骤(2)(A)都会收到命令v,因为叛徒下属并不能伪造指挥官签名,因此在步骤(2)(B)并不能对消息进行篡改,所以诚实的下属在步骤(2)(B)并不能收到除了v以外的其他命令
- 这就保证了集合Vi只会有一个命令v,再经由步骤(3)的choice函数,最后每一个下属的命令都是一样的,也即满足IC2
- 因为在指挥官是诚实的情况下IC1可以由IC2推导出,因此只需要证明指挥官是叛徒的情况下是否符合IC1即可
- 若两个下属i,j最后在步骤3服从相同的命令,那么他们俩在步骤(2)的 Vi , Vj 也是一样的
- 因此,证明IC1就是证明
- 如果i在步骤(2)将v加入到集合Vi,那么j也一定在步骤(2)把v加入到Vj中
- 如果i在步骤(2)(A)收到了命令v,那么他就会将其在步骤(2)(A)(ii)发送给j,所以j就会收到这一信息(因为消息的A1约束)
- 如果i在步骤(2)(B)将命令添加到自身的Vi中,那他一定收到了信息v : 0 : j1 : … : jk
- 如果j是其中一个jr那么通过A4约束,他一定已经收到了消息v,如果j不在该签名队列(j1 : … : jk)中,分两种情况:
- 1. k
- 2. k = m的话,除叛徒指挥官之外,n-1个下属中最多还有m-1个叛徒下属,因此至少在j1,j2 … : jm中,至少有一个下属是诚实的;那么这个诚实的下属也在他收到消息的第一时间将v发给j
- 所以无论如何j还是会收到v
- 综上所述,SM(m)算法满足IC1&IC2,定理2成立
-
5-通信路径缺失
- 前文所述都是将军之间可以两两直接发送消息的情况,以下讨论移除这一假设,对算法OM(m)和SM(m)进行扩展
- 3-正则图(3-regular graph):每一个节点的度都是3;如下图所示:
- 如果两个将军有边相连,那么称这两个将军为邻居
- 定义1:
- (a)节点i的邻居正则集合(regular set of neighbors)是满足以下条件的点集i1 , …, ip
- (i)每个元素都是节点i的邻居
- (ii)对于每一个不同于i的将军k,存在至少两条从ij到k的不经过i且只有终点k重合的路径
- (b)如果图G的每一个点都有一个由p个点构成的regular set of neighbors,那么图G被称为p-正则图(p-regular)
- (a)节点i的邻居正则集合(regular set of neighbors)是满足以下条件的点集i1 , …, ip
- 图6就是一个3−regular,图7就不是,因为中心点没有有3个点的regular set of neighbors
-
对OM(m)的改进OM(m,p)
- 前提:需要将军(包括叛徒将军)之间的能够发送消息的图是一个3m−regular
- 对所有的正数m,p,如果图G是一个p−regular,定义算法OM(m,p)如下所示:
- (0)选择指挥官的由p个下属组成的正则邻居集合N
- (1)指挥官将其值发给N中的每一个下属
- (2)对N中的每一个下属i,以Vi代表i收到的值,或RETREAT代表未收到任何值;下属i按照如下方式将Vi发给其他下属k:
- (A)如果m=1,那么沿着路径Pi,k发送,该路径的存在是由定义1的条件(ii)保证的
- (B)如果m>1,那么他就作为算法OM(m-1,p-1)中的发令者,同时此时的将军图是通过将原始的发令者从图G中删除得到的
- (3)对于任意的k,及N(N={i1,…,ip})中的任意不等于k的i,让vi代表下属k在步骤(2)中从下属i处收到的值,如果没有收到值令其等于RETREAT;下属k使用值majority(vi1,…,vip)
- 注意:从p-regular图中删除一个节点后可以得到一个(p-1)-regular图;因此,可以在步骤(2)中应用算法OM(m-1,p-1)
- 现在我们证明如果最多有m个叛徒,那么OM(m,3m)解决了拜占庭将军问题
- 该证明类似于算法OM(m)的证明,因此我们只是简单的描述下
- 首先从引理1的一个扩展开始:
- 引理2:对于任意的m>0及任意的p>=2k+m,如果最多有k个叛徒,算法OM(m,p)满足条件IC2
- 证明:对于m=1,可以看出每个下属会得到majority(v1,…,vp)的值,其中的每个值vi是发令者通过一条与发送给他的其他值的发送路径不相交的一条路径发送的(此处的发令者是指步骤(2)中的N中的某个将军,并不是特指(1)中的那个原始的发令者)
- 由于最多有k个叛徒而且p>=2k+1,因此超过一半的路径都是完全由忠诚的下属组成的(总共有p条路径,只有k个叛徒,p>=2k+1,即使一条路径上只有一个叛徒,那么最多有k条路径上有叛徒)
- 因此,如果发令者是诚实的,那么有一半以上的vi值都是他发送的那个值,这样就保证满足了IC2
- 现在假设对于m-1,m>1 引理2成立
- 如果发令者是忠诚的,那么N中的P个下属都会得到正确的值
- 因为p>2k,因此他们中大多数都是忠诚的,根据归纳假设,他们中的每个人都会给每个诚实的下属发送正确的值
- 因此,每个忠诚的下属,会收到半数以上的正确值,因此在步骤(3)他们会得到正确的值
- 定理3:对于任意的m>0及任意的p>=3m,如果最多有m个叛徒,那么算法OM(m,p)解决了拜占庭将军问题
- 证明:根据引理2令k=m,我们可以得到OM(m,p)满足IC2
- 如果发令者是诚实的,那么IC1可以由IC2导出,因此我们只需要证明发令者是叛徒的情况下的IC1即可
- 为此,我们需要证明在步骤(3),每个忠诚的下属得到相同的vi值的集合
- 如果m=1,很明显成立(此时只有一个叛徒,而且他是发令者)
- 因为所有的下属包括N中的那些,都是诚实的,并且路径Pi,k不经过发令者
- 如果m>1,可以使用一个归纳法证明,因为p>=3m,得出p-1>=3(m-1)
- 我们关于算法OM(m)的扩展要求图G是一个3m-regular图,是一个相对比较强的联通性假设
- 实际上,如果仅有3m+1个将军,3m-regularity实际上就是全互联,而算法OM(m,3m)实际上也变成了OM(m)算法
- 与此相比,算法SM(m)很容易扩展到可能的最弱的连通性假设
- 首先,我们来看保证拜占庭将军可解需要何种程度的连通性
- IC2要求一个忠诚的下属遵从忠诚的发令者,很明显如果发令者无法与该下属通信是不可能达到的
- 尤其是如果发令者发到该下属的消息都要经过一些叛徒转发,那么就没有方法保证该下属可以得到发令者的命令
- 类似的,如果两个下属之间只能通过一些叛变的中间者进行通信,他们条件IC1也无法满足
- 因此对于拜占庭将军问题可解的最弱的连通性假设就是:由忠诚的将军们组成的子图是连通的
- 可以证明,在该假设下,算法SM(n-2)是一个可行解,此处n代表将军的个数-无论有多少个叛徒
- 当然,我们必须要修改该算法,使得他只能向那些可以通信的对象发送消息
- 详细来说,就是在步骤(1),发令者只能向他的邻居下属发送消息,在步骤(2)(B),只能向那些不在jr中的邻居下属发送信息
- 下面我们来证明一个更一般的结论,首先需要知道图的直径是指图中任意两节点间的最短路径的长度的最大值
- 定理4:对于任意的m和d,如果最多有m个叛徒及忠诚的将军组成的子图的直径为d,那么算法SM(m+d-1)(加入了上面的改动后的算法)可以解决拜占庭将军问题
- 证明:证明过程很类似于定理2
- 首先证明IC2,根据假设,从忠诚的发令者与一个下属i之间存在一条路径,该路径只是经过d-1个或者更少的忠诚下属
- 这些下属在命令到达i之前,可以正确的转发它,如前面所述,假设A4可以防止一个叛徒伪造一个不同的命令
- 为了证明IC1,我们假设发令者是个叛徒,接下来需要说明,一个忠诚下属收到的任何命令,另一个忠诚的下属j也都能收到
- 假设i收到了一个未被j签名的消息v:0:j1:…:jk
- 如果k
- 如果k>=m,那么之前的m个签名者中至少有一个是忠诚的,而且他一定已经将给命令发送给了他所有的邻居,这样它会被忠诚的下属们继续转发,也会在接下来的d-1步内j就会收到该消息
- 证明:让d代表忠诚的将军的图的直径;由于一个连通图的直径肯定小于节点总数,同时忠诚将军的个数肯定大于d,反过来叛徒的个数肯定小于n-d;令m=n-d-1代入定理4,得到SM(n-d-1+d-1)即SM(n-2)
- 定理4假设忠诚的将军组成的图是连通的;即使该条件不成立,上面的证明可以很容易扩展而得到如下的结论:
- 当最多有m个叛徒的时候,算法SM(m+d-1)有如下属性:
- 1-图中由最多d个忠诚下属连接的任意两个忠诚下属会遵守相同的命令
- 2-如果发令者是忠诚的,那么与发令者之间存在一条由最多m+d个忠诚下属组成的路径的忠诚下属将会遵守发令者的命令
6-可靠性系统
可靠性系统的要素
- 除了在内部使用可靠性电路组件外,我们所知的实现可靠计算机系统的唯一方式就是使用几个不同的处理器来计算相同的结果,然后在它们的输出结果上执行多数决的投票来确定一个值(投票可能是在系统内部进行的,也可能是该输出的用户在外部进行的)
- 无论是在实现可靠计算机中通过冗余电路来避免独立芯片的失败,还是在弹道导弹防御系统中使用冗余计算站点来避免核攻击中的网点破坏,都是如此
- 唯一的区别就是被备份的处理单元的大小规模
- 多数决的投票的使用基于这样的一个假设:所有的正常的处理单元应该产生相同的输出结果
- 当它们都使用相同的输入时,这是正确的
- 然而,一个输入数据来自一个独立的物理单元,比如来自可靠计算机系统的其他电路单元,或者来自于导弹防御系统中的一个雷达站,一个故障组件也可能会为不同的处理单元提供不同的值
- 更进一步的,从同一个输入单元获取输入的不同的处理单元也可能获得不同的输入,因为在他们读取时输入值可能是不断变化的
- 比如,两个处理器去读取一个在运行的时钟,一个可能读取到老的时间,一个可能读到新的,只能通过对该时钟的读取进行同步才能防止这种情况
- 为了让基于多数决的投票可以构建可靠性的系统,需要满足如下两个条件:
- 一致性(Safety)、可用性(Liveness)(分别对应下列1,2)
- 1-所有的正常处理单元必须使用相同的输入值(这样他们才会产生相同的输出)
- 2-如果输入单元是正常的,那么每个正常的进程都应该使用它提供的值作为输入(这样他们才能产生正确的结果)
- 这正是我们的交互一致性条件IC1和IC2,至少发令者变成了输入产生单元,下属变成了处理单元,忠诚意味着正常(nonfaulty)
- 为这样的问题提供一个硬件级的解决方案看起来是很吸引人的
- 比如,有人认为可以通过让所有的处理单元从同一条线路上读取输入来保证它们可以获取相同的值
- 但是,一个出错的处理单元可能会在线路上发送边缘信号—这种信号某些处理器可能作为0处理,但是其他的可能作为1处理
- 因此不存在一种方法可以保证不同的处理器会从可能出错的输入单元上获取相同的值,除非让处理器相互之间可以通信来解决拜占庭将军问题
- 当然一个出错的输入单元可能会提供无意义的输入值
- 拜占庭将军解决方案可以做的就是保证所有的处理单元可以使用相同的输入值
- 如果输入是一个很重要的部分,那么应该有多个独立的输入单元提供冗余值
- 比如在一个导弹防御体系中,除了有冗余的处理站点外,还应该具有冗余的雷达
- 然而,输入的冗余无法达到可靠性
- 仍然有必要保证正常的处理单元可以通过使用冗余数据产生相同的输出
- 对于输入设备是正常的但是由于读取时它的值仍在变化的情况,我们仍然希望那些正常的处理单元可以获取合理的输入值
- 可以看到,如果函数majority和choice被设定为中位数函数,那么我们的算法会具有如下的属性:
- 正常的处理单元得到的值将落在输入单元提供的值的边界之内
- 因此只要输入单元提供一个合理的值的边界,那么正常的处理单元将会得到一个合理的值
消息传递系统的约束
- 在现实系统中,通信线路可能出错
- 对于算法OM(m)和OM(m,p),连接两个处理单元间的通信线路出错无法与其中的一个处理单元出错区分出来
- 因此,我们仅能保证这些算法在出现m个失败时可以工作,可能是处理器也可能是通信线路出错了(当然,连接到相同处理器上的通信线路错误等价于那个处理器的失败)
- 如果我们假设通信线路错误不会导致签名信息的伪造(下面可以发现该假设十分合理),那么我们的签名信息算法SM(m)就不会受到通信线路错误的影响
- 更准确的说,即使出现通信线路错误,定理4依然合法
- 这样一个通信线路错误与简单的移除该通信线路具有相同的影响—只是降低了图的连通性
- 这条实际上主要是要求一个出错的处理单元不能伪装成一个正常的
- 在实际中,这意味着进程间的通信必须是通过固定线路而不是通过某些消息传递交换网络(如果使用的是交换网络,那么必须考虑网络节点的失效,拜占庭将军问题再次出现)
- 注意如果条件A4满足,同时所有的消息都是签名的,那么A2就不是必要的
- 因为进程的不可模仿性通过消息的签名就可以达到
- 消息的缺席只能通过在固定时长内没有到达来检测,换句话说,需要通过使用某些超时约定
- 使用超时机制来达到条件A3,需要如下2个假设:
- 1-消息的产生和传输所需的时间有一个固定的最大时长
- 2-发送者与接收者有一个固定误差的同步时钟(类似于时间相差20ms)
- 第一个假设的必要性是很明显的,因为接收者必须知道他需要花多长时间等待消息的到达
- 第二个假设的必要性很不明显;然而可以证明,如果要解决拜占庭将军问题,需要该假设或者是等价于它的某个假设;更准确的说,假设有一个算法,在该算法中,将军们只能在如下的情形下采取行动:
- 1-在某个固定的初始时间(对于所有的将军来说该值相同)
- 2-收到消息的时候
- 3-当一个随机选择的时长过后(比如一个将军可以将计时器设定为一个随机值,在时间到时才能继续行动)
- (上面代表了我们能想象出来的不需要构建同步时钟的最通常的一类算法)
- 可以证明,如果消息可能以任意快的速率传输即使存在一个上界,那么不存在解决拜占庭将军问题的此类算法
- 甚至即使我们限制叛徒的错误行为只是无法发送消息,这种情况下依然是无解的
- 该结论的证明超过了本篇文章的内容
- 需要注意的是,如果对传输延时上除了上界限制之外,再添加一个下界限制就允许处理单元通过来回的传递消息来实现时钟
- 上面的两个假设,使得检测未发送的消息变得很简单
- 令u代表最大的消息生成和传输延时,假设正常处理单元在任何时刻的时钟误差最大为t
- 这样如果一个正常处理单元在他的时钟时间T生成的任何消息,消息会在接收者的时钟时间T+u+t内到达
- 因此,如果接收者在那时还未收到该消息,那么它就认为发送者没有发送该消息(如果它在之后到达,那么发送者一定出错了,因此算法的正确性不能依赖于正在发送的消息)
- 通过固定输入处理单元发送值的时间,处理单元就可以确定等待应该等待消息到何时
- 比如,在算法SM(m)中,一个处理单元对于任何具有k个签名的消息必须等待到时间T0+k(u+t),T0代表该处理单元在发令者开始执行算法时的它自己的时钟时间
- 没有任何两个时钟具有相同的速率,因此无论处理单元间的时钟一开始无论同步的多么精确,最后他们都会相差很大,除非会周期性的进行重新的同步
- 因此现在我们需要解决让处理单元时钟同步在一定偏差之内,即使有的处理单元是出错的
- 该问题本身是一个与拜占庭将军问题难度相当的问题
- 时钟同步问题的解与拜占庭将军问题的解联系紧密,我们会在未来的文章中进行描述
- 假设进程i从数据M生成的签名为Si(M)
- 那么一个经签名的信息就由一个(M,Si(M))对组成
- 为了满足A4的(a)(b)两个要求,函数Si必须具有如下两个属性:
- (a)如果处理单元i是正常的,那么任何出错单元都不能生成Si(M)
- (b)给定M和X,任何进程都可以确定X是否等于Si(M)
- 属性(a)不可能绝对满足,因为Si(M)仅仅是一个数据项,一个出错的处理单元可能生成任意的数据项(这意味着它也可能刚好生成Si(M))
- 但是我们可以让这种出错情况的概率尽可能的小,从而也可以让系统尽可能的稳定
- 如何做到这点依赖于我们期望碰到的出错类型;比如如下两种情况:
- 1-随机故障
- 令Si为一个合适的随机化函数,我们可以让一个出现随机故障的处理单元生成一个正确的签名的概率等价于通过随机选择函数来完成这件事的概率,即可能的签名的数目的倒数
- 下面介绍可以达到该目的的一种方法
- 假设消息被编码成小于P的正整数,P是2的幂(实际上消息本质上也是二进制01码,因此只需要保证其长度小于P的长度即可)
- 令Si(M)=(M*Ki)mod Pi,Ki是一个随机选择的小于P的奇数
- 令Ki^-1为满足Ki* Ki^-1=1 mod P的唯一一个数,一个处理单元可以通过测试M是否等于(X* Ki^-1)mod P来测试X是否等于Si(M)
- 如果一个处理单元的内存中没有值Ki,那么它为一个消息M生成正确的签名M*Ki的概率是1/P:这也是通过随机选择来生成的概率(如果处理单元能通过某种过程获得Ki,那么出错的处理器j在计算Sj(M)的时候就有更大的概率可能将Sj替换为Si来伪造i的签名)(所以这样看来其实该机制也类似于公钥签名机制,(Ki,P)可以看做私钥,而(Ki^-1,P)则可以看做公钥
- 可能还有一个问题是Ki可以很容易通过(Ki^-1,P)求出来,当然这也是与公钥机制的区别
- 但是这不影响对问题的解决,因为该假设是假设错误是随机的,如果利用(Ki^-1,P)计算Ki再去伪造应该算是恶意攻击了,就是下面这个假设的范畴了
- 2-恶意攻击
- 如果出错的处理单元是由恶意攻击导致—比如一个正常的处理单元可能正被一个企图破坏整个系统的人操纵
- 那么签名函数Si的构建就变成了一个密码学问题
- 需要注意的是如果处理单元已经看到过消息M的签名,那么下次它就很容易生成Si(M)
- 因此需要保证不能重复对相同的消息签名
- 这就意味着,使用SM(m)算法重复的发送一系列值的时候,需要给这些值增加一个序列号来保证它们的唯一性(之所以要加入序列号,是因为如果不加下属们就很容易伪造签名,比如他收到了一个(M,S1(M),S2(M)…Sk(M))消息,同时之前也收到过值为M’的消息,同时由于不断的发送,他可能已经收到过针对M’的所有签名,这样他就可以把(M,S1(M),S2(M)…Sk(M))修改成(M’,S1(M’),S2(M’)…Sk(M’)),这样就达到了伪造的目的:他修改了M的值,但是将军们的签名还都正确;所以需要加入序列号以提供保证,使得将军们不会再次发出相同的消息值,也就没法利用之前收到的消息进行伪造)
- 最后看下如何通过上面的方法来保证A4假设呢?
- 首先假设A4如何保证消息不被伪造,先看下属在伪造一个消息时需要做哪些事情:
- 根据前面,我们知道每个下属收到的是形如(M,S1(M),S2(M)…Sk(M))的消息,他如果要修改该消息,首先要修改M的内容,然后再修改签名1到k
- 但是根据假设它实际上无法修改经过忠诚者签名的那些消息,根据上面的方法,每个下属接受到消息后只需要去验证M是否等于(Si(M)* (Ki^-1))mod P,即可验证签名的真伪,所以只要保证忠诚的将军的Ki不被泄露即可
- 另一方面对于叛变的将军,并没有任何的限制,比如叛变的将军可能会告诉另一个将军自己的私钥(Ki,P)这样他的签名就可以被伪造了,但是忠诚的将军不会这么做,所以他的签名就能保证不可伪造,但该假设并没有对叛变的将军做出这种保证,也就是说这种签名存在的情况下,叛变的将军们依然可以相互勾结去伪造出发令者的命令
7-小结
8-参考文献
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
一、背景 周所周知,Kafka是一个非常成熟的消息产品,开源社区也已经经历了多年的不断迭代,特性列表更是能装下好几马车,比如:幂等消息、事务支持、多副本高可用、ACL、Auto Rebalance、HW、Leader Epoch、Time Index、Prod…