PBFT共识算法 (4)

视图更换协议需要解决的问题是如何保证已经被非拜占庭服务器执行的请求不被更改。由于系统达成一致性之后至少有\(f+1\)台非拜占庭服务器节点执行了请求,所以目前采用的方法是:由新的主节点收集至少\(2f+1\)台服务器节点的状态信息(也就是上面在构造消息时所需的各种消息集合),这些状态信息中一定包含所有执行过的请求;然后,新主节点将这些状态信息发送给所有的服务器,服务器按照相同的原则将在上一个主节点完成的请求同步一遍,同步之后,所有的节点都处于相同的状态,这时就可以开始执行新的请求。

若干细节问题的思考 在3阶段协议中,对收到的消息都要进行消息合法性检查、视图检查、水线检查这3项检查,为什么呢?

这3项检查是十分有必要的,添加消息签名是为了验证投票是否合法,正确统计合法票数,不能是随便一个不知道的节点都能投票,那我怎么验证到底是谁投的呀。也就是说,要通过消息签名的方式确认消息来源,通过消息摘要的方式,确认消息没有被篡改。当然,考虑到性能因素,也可以使用消息认证码(MAC),以节省大量加解密的性能开销。PBFT算法,可以容忍节点作恶,消息丢失、延时、乱序,但消息不能被篡改。

视图检查比较容易理解,所有节点必须在同一个配置下才能正常工作。如果节点的视图配置不一致,比如主节点不一致、节点数量不一致,那统计合法票数的时候,真没法干了。

水线检查,是检查点协议的一部分,在工程实现时,不是所有的请求我都有处理,比如,你收到一个历史投票信息,你还有必要处理吗?当然,它的作用不止于此,还可以防止恶意节点选择一个非常大的序列号而耗尽序列号空间,例如,当一个节点分配了超过H上限的序列号,这时,正常节点会拒绝这个请求从而阻止了恶意节点分配的远超过H的序列号。

3阶段协议中每一阶段的意义是什么?

论文中有如下表述:

The three phases are pre-prepare, prepare, and commit.The pre-prepare and prepare phases are used to totally order requests sent in the same view even when the primary, which proposes the ordering of requests, is faulty. The prepare and commit phases are used to ensure that requests that commit are totally ordered across views.

即,pre-prepare和prepare阶段,主要的作用就是定序,个人理解就是要确认有足够数量的节点收到同一请求,并且与自己所收到的请求相一致。prepare以及commit阶段是确认大家执行的同一请求。

为什么是\(3f+1\)

我们知道PBFT的容错能力为不超过三分之一,即\(n=3f+1\)\(f\)为拜占庭节点数量。但这个公式是怎么来的呢?论文中有这么一段论述可以帮助我们去理解:

The resiliency of our algorithm is optimal: \(3f+1\) is the minimum number of replicas that allow an asynchronous system to provide the safety and liveness properties when up to \(f\) replicas are faulty. This many replicas are needed because it must be possible to proceed after communicating with \(n-f\) replicas, since \(f\) replicas might be faulty and not responding. However, it is possible that the \(f\) replicas that did not respond are not faulty and, therefore, \(f\) of those that responded might be faulty. Even so, there must still be enough responses that those from non-faulty replicas outnumber those from faulty ones, i.e., \(n-2f>f\). Therefore \(n>3f\).

意思就是,在一个容忍\(f\)个错误节点的系统中,系统至少要\(3f+1\)个节点才能保证系统安全可靠。为什么呢?因为在所有\(n\)个节点中,有\(f\)个节点可能因故障而没有回应(或者投票),而在回应的\(n-f\)中又有可能有\(f\)个是恶意节点的回应,即使如此,也要保证正常节点的投票要多于恶意节点的投票数量,即\(n-f-f>f\),推出\(n>3f\)

PBFT对比Raft

PBFT对比Raft,最大的不同在于解决的问题不一样,虽然都是共识算法,但一个解决的拜占庭问题,另一个则解决的非拜占庭问题。从算法细节上来看,Raft中的领导者是强领导者,即,一切领导者说了算,但PBFT中对应的主节点却不是,因为不能保证主节点不是拜占庭节点,万一主节点作恶,从节点要有发现主节点是恶意节点的能力,并及时触发视图更换协议更换主节点。从算法消耗的资源来看,明显PBFT要更复杂,投票数明显多于Raft,不但要主从节点交互,还有从节点与从节点互相交互,所以,其性能也一定比Raft低,这是肯定的,因为PBFT解决的问题比Raft更复杂,一定程度上可以认为Raft是PBFT的子集,如果你把PBFT三阶段协议中从节点与从节点交互的那部分去掉,只保留主节点与从节点交互的那部分,你会发现,好像还蛮像的。从另一个方面说,Raft算法,因为没有拜占庭节点的存在,领导者节点一定是对的,从节点一切听领导的就是。但是在PBFT中,从节点就不能光听主节点的,万一主节点也是坏人咋办?怎么解决这个问题呢?显然,只听主节点肯定是不行的,我还要看看其他节点的意见,如果有足额的节点认为是对的,就同意。怎么确定足额节点数到底是多少呢?上面有讲到过。所以,相比Raft,PBFT多了从节点与从节点的消息交互。

PBFT的时间复杂度分析

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyygjj.html