https://www.cnblogs.com/binyue/p/8647743.html 作者:邴越 关注思维和方法论,公众号:越读价值

分布式一致性问题,区块链里体现就是共识问题。
共识机制就是在一个群体中的个体通过某种方式达成一致性的一种机制,比如在一个团队、或者一个公司里的个体意见不一致时,就需要有一个领导,由领导来做决定,保证团队达成共识。
目前的共识算法,主要有基于算力的POW,基于股权的POS和基于投票的DPOS算法,以及著名的拜占庭容错算法。

一、共识机制

团队里的共识机制延伸到普通的分布式系统里面,就是系统需要有一个master,系统的所有决定都由master来达成共识,在分布式系统里面master的选举其实就是基于某种共识机制达成共识。
到了区块链中,由于区块链是一种去中心化的分布式系统,所以区块链中是没有类似于团队里的领导,以及分布式系统中的master的角色,这样就需要有某种共识机制,以便保证系统一致性。
实际上当节点之间的通信网络不可靠的情况下,系统是无法达成共识的,具体原因请参考“两军问题”。
即使在网络通信可靠的情况下,一个可扩展的分布式系统的共识问题也是无解的。这个结论被称为”FLP不可能性原理“。一般的把故障(不响应)即信道不可靠的情况称为”非拜占庭错误“,恶意响应(即系统被攻击)称为”拜占庭错误“。

二、拜占庭将军问题

拜占庭将军问题是一个共识问题: 首先由Leslie Lamport与另外两人在1982年提出,被称为The Byzantine Generals Problem或者Byzantine Failure。核心描述是军中可能有叛徒,却要保证进攻一致,由此引申到计算领域,发展成了一种容错理论。
论文地址:
The Byzantine Generals Problem
一群将军想要实现某一个目标(一致进攻或者一致撤退),但是单独行动行不通,必须合作,达成共识;由于叛徒的存在,将军们不知道应该如何达到一致。

1.两军问题和TCP协议

拜占庭将军问题中并不去考虑通信兵是否会被截获或无法传达信息等问题,即消息传递的信道绝无问。Lamport已经证明了在消息可能丢失的不可靠信道上试图通过消息传递的方式达到一致性是不可能的。所以,在研究拜占庭将军问题的时候,我们已经假定了信道是没有问题的,并在这个前提下,去做一致性和容错性相关研究。
如果需要考虑信道是有问题的,这涉及到了另一个两军问题,两军问题在经典情境下是不可解的,现代通信系统中应用三次握手与TCP协议来处理此类问题,不过这也只是一种相对可靠的方式。

2.口头协议算法

Lamport论文:
从分布式一致性到共识机制-拜占庭问题 - 图1
对于这个算法需要说明的是:
(1) 在第一轮将军会把消息发送给所有的副官,第i个副官收到的记为 Vi。如 1(这里代表的是Attack)
(2) 在第二轮里面,Li(即第i个副官)会怀疑将军发来的消息Vi是对还是错,于是他会问其余的副官。这样他就会得到剩下的(n-2)个副官的值。 i从1到n-1,所以每个副官都会得到剩余的n-2个副官手里的Vi。在这一步骤里,忠诚的副官j会直接将自己的 Vj发送给其它人。叛徒则会发假消息。
在n=7,m=2的时候 如果将军是忠臣的话,那么在第二轮忠诚的副官确实已经可以判断出要做的决定,因为他们会收到(1 1 1 0 0 )再加上将军发来的1就是 1 1 1 1 0 0 但是这个算法是递归的所有必须要到第三轮。并且如果将军是个叛徒的话,那么第二轮有情形是做不出决定的。
这里对进入第三轮的解释是,如L1收到其它L2~L6发来的Vj, 但是他要怀疑准确性,比如L1会想L2发给自己是否是正确的呢?那么就进入第三轮进行投票。
(3)在第三轮里面,接着(2)中后面的问题。L1会依次询问L3,4,5,6 ,问他们上一轮L2给他们发了什么,然后L1会得到在(2)中 L2->L3, L2->L4,L2->L5, L2->L6的值 这样再结合自己的L2->L1的值,从这5个里面用majority函数投出决定得到L2发给自己的消息值。依次再进行L3,L4,L5,L6在第二轮中发给自己的消息的确认。
这样L1就完成了第二轮的确认。之后L1再从第一步中将军发给自己的vi和第二轮中确定的5个值中投出自己的决定。
其余的L2,L3后续也进行同样的步骤。

3.书面协议算法

书面协议和口头协议最大区别是,副官可以叛变并且说谎,也就是中国人讲的口说无凭。
现在我们给消息加上将军的签名,必须通过签名来验证,就是为了防止说谎。
从分布式一致性到共识机制-拜占庭问题 - 图2
在签名算法中加了两个条件:

  • 忠诚将军的签名是不能伪造的,内容修改可检测
  • 任何人都可以识别将军的签名,叛徒可以伪造叛徒司令的签名

这里Lamport规定,每条消息只可以复制,然后加上自己的姓名再发出去。
Lamport论文:
从分布式一致性到共识机制-拜占庭问题 - 图3
从分布式一致性到共识机制-拜占庭问题 - 图4

三、PBFT 实用拜占庭算法

这里借用一个类比(知乎[Devin Zeng]:

PBFT算法要求至少要4个参与者,一个被选举为总司令,3个师长。总统对总司令下达命令,你们向前行军500公里,总司令就会给3个师长发命令向前行军500公里。3个军长收到消息后会执行命令,并汇报结果。A师长说我在首都以东500公里,B师长说我在首都以东500公里,C师长说我在首都以东250公里。总司令总结3个师长的汇报,发现首都以东500公里占多数(2票>1票),所以就会忽略C军长的汇报结果,给总统说,好了,现在部队是在首都以东500公里了。

1.五个概念

client:请求(request)资源者
replica:副本,所有参与提供服务的节点
primary:承担起提供服务主要职责的节点
backup:其他副本,但相对于primary角色
view:处于存在primary-bakup场景中的相对稳定的关系,叫视图。
如果primary出现故障,这种相对稳定的视图关系就会转变(transit),某个backup转变为primary。

2.四个阶段

client请求阶段,客户端请求资源。
预准备(pre-prepare):主节点向所有backup节点发送预准备消息,其中包括当前视图编号,client请求以及请求摘要,签名是否一致等。
准备(prepare):包括主节点在内的所有副本节点在收到准备消息之后,对消息的签名是否正确,视图编号是否一致,以及消息序号是否满足水线限制这三个条件进行验证,如果验证通过则把这个准备消息写入消息日志中。
确认(commit):每个副本接受确认消息的条件是:1)签名正确;2)消息的视图编号与节点的当前视图编号一致;3)消息的序号n满足水线条件,在h和H之间。一旦确认消息的接受条件满足了,则该副本节点将确认消息写入消息日志中。
回复(reply):结果反馈。

共识真的不能达成吗

关于拜占庭等问题的讨论只是学术上极端情况下的理论值,现实中的物理系统远比这个要复杂,我们付出一定的代价总是能做到一定程度的共识。
参考
拜占庭将军问题深入探讨