Practical byzantine fault tolerance,拜占庭容错算法。PBFT中各节点首先选举出一个leader节点,客户端向leader节点发送请求,leader节点通过广播通知所有副本节点,主节点与副本节点之间通过多次通信,所有准备阶段的节点向所有节点发送最终确认信息,最后所有确认阶段的节点向客户端发送回复信息。PBFT可以很好地解决拜占庭将军问题,但是其无法支持大规模节点,且节点无法自由进出,仅适用于联盟链。
PBFT(Practical byzantine fault tolerance拜占庭容错算法,分布式一致性算法:去中心化、大规模节点无法支持、效率低)
多个节点中提前选出一个领袖节点,领袖节点代替客户端询问副本节点的意见,客户端最后收集所有节点的意见,进行总结得出最后决定。
Hyperledger有Peer(记账节点:维护账本和状态,上传交易)、Endorsing peer(背书节点:执行智能合约,模拟交易)、Ordering peer(排序节点、共识节点:排序交易,打包交易,生成交易)三种节点
PBFT有leader.validating.non-validating三种节点
如四个节点接收到的顺序不同,则先随机选出(可能进行了投票机制)一个领袖节点,其他节点调整到与领袖节点一致
PBFT举例:
PBFT算法要求至少要4个参与者,一个被选举为军长,3个师长。军长接到总司令命令:你们向前行军500公里。军长就会给3个师长发命令向前行军500公里。3个师长收到消息后会执行命令,并汇报结果。A师长说我在首都以东500公里,B师长说我在首都以东500公里,C师长说我在首都以东250公里。军长总结3个师长的汇报,发现首都以东500公里占多数(2票>1票),所以就会忽略C师长的汇报结果,给总司令汇报说,好了,现在部队是在首都以东500公里了。这就是PBFT算法。
client:请求(request)自愿者,上例中指总司令。
replica:副本,所有参与提供服务的节点,上例指军长和师长
primary:承担起提供服务主要职责的节点,上例是军长
backup:其他副本,但相对于primary角色。上例指师长。
view:处于存在primary-bakup场景中的相对稳定的关系,叫视图。
如果primary出现故障,这种相对稳定的视图关系就会转变(transit)。比如军长叛逃(出现故障,对外表现为不可见),那么某个师长就会转变成为军长。系统也就从视图a转变为视图b(a,b均为整数)。
下图展示了在没有发生主节点失效的情况下算法的正常执行流程,其中副本0是主节点,副本3是失效节点,而C是客户端。通过这个例子,也帮助我们理解n>=3f+1的算法。
该算法实现主要分为以下几个步骤:1、客户端向主节点发出请求;2、主节点通过广播通知所有副本节点;3、所有正常副本节点向所有节点(包括主节点)发送请求;4、所有准备阶段的节点向所有节点发送确认信息;5、所有确认阶段的节点向客户端发送回复信息;
这是一种基于消息传递的一致性算法,算法经过三个阶段达成一致性,这些阶段可能因为失败而重复进行。
在N ≥ 3F+1 的情况下一致性是可能解决的。其中,N 为计算机总数,F 为有问题计算机总数。信息在计算机间互相交换后,各计算机列出所有得到的信息,以大多数的结果作为解决办法。只要系统中有2/3 的节点是正常工作的,就可以保证一致性。
PBFT 算法的过程如下。
客户端向主节点发送请求调用服务。客户端c 向主节点发送<REQUEST,o,t,c> 请求执行操作o,这里时间戳t用来保证客户端请求只会执行一次。每个由副本节点发给客户端的消息都包含了当前的视图编号,使得客户端能够跟踪视图编号,从而进一步推算出当前主节点的编号。客户端通过点对点消息向它自己认为的主节点发送请求,然后主节点自动将该请求向所有备份节点进行广播。
视图是连续编号的整数。主节点由公式p=v mod|R| 计算得到,这里v 是视图编号,p 是副本编号,|R| 是副本集合的个数。副本发给客户端的响应为<REPLY,v,t,c,i,r>,v 是视图编号,t 是时间戳,i 是副本的编号,r 是请求执行的结果。主节点通过广播将请求发送给其他副本,然后就开始执行三个阶段的任务。
(1)预准备阶段。主节点给收到的请求分配一个序列号n,然后向所有备份节点群发预准备消息,预准备消息的格式为<<PRE-PREPARE,v,n,d>,m>,这里v 是视图编号,m是客户端发送的请求消息,d 是请求消息m 的摘要。
(2) 准备阶段。如果备份节点i 接受了预准备消息<<PRE-PREPARE,v,n,d>,m>,则进入准备阶段。在准备阶段时,该节点向所有副本节点发送准备消息<PREPARE,v,n,d,i>,并且将预准备消息和准备消息写入自己的消息日志。如果看预准备消息不顺眼,就什么都不做。
(3) 确认阶段。当(m,v,n,i) 条件为真时, 副本i 将<COMMIT,v,n,D(m),i> 向其他副本节点进行广播,于是就进入了确认阶段。所有副本都执行请求并将结果发回客户端。客户端需要等待f+1 个不同副本节点发回相同的结果,作为整个操作的最终结果。
如果客户端没有在有限时间内收到回复,请求将向所有副本节点进行广播。如果请求已在副本节点处理过了,副本就向客户端重发一遍执行结果。如果请求没有在副本节点处理过,该副本节点将把请求转发给主节点。如果主节点没有将该请求进行广播,那么就有认为主节点失效,如果有足够多的副本节点认为主节点失效,则会触发一次视图变更。
拜占庭的问题中,如果总的节点数为N,恶意将军数为F,当N≥3F+1时,拜占庭问题才有解决方法,也就是BFT(Byzantine fault tolerant)算法.