分布式一致性协议之 PBFT

BFT

拜占庭容错(Byzantine Fault Tolerance,BFT)是一类分布式计算领域的容错技术。拜占庭假设是对现实世界的模型化,由于硬件错误、网络拥塞或中断以及遭到恶意攻击等原因,计算机和网络可能出现不可预料的行为。拜占庭容错技术被设计用来处理这些异常行为,并满足所要解决的问题的规范要求。

PBFT

实用拜占庭容错(Practical Byzantine Fault Tolerance,PBFT)是经过优化,将将拜占庭容错算法从指数级别降低到多项式级别。在叛变节点不超过总节点的1/3情况下(最坏需要F+1轮交互,F为叛变节点),可以确保整个系统达成共识。

至于1/3 怎么来的,如何证明的,可以去看Leslie Lamport等人的论文《Reaching agreement  in the presence of faults》。我没看,估计我也不懂。我就把这个当作公理了(类似1+1=2),少点烦恼。

PBFT算法采用密码学相关技术(RSA签名算法、消息验证编码 和摘要)确保消息传递过程无法被篡改和破坏。

PBFT算法描述

pbft算法的基本流程主要有以下几步:

1、首先轮换或者随机算法选出某个节点为主节点,此后只要主节点不换,则视图(view)始终不变。

2、某个view中,客户端把请求发送给主节点,主节点负责广播请求到所有从节点

3、所有节点处理完请求,把结果返回给客户端。客户端检查是否收到了至少F+1个来自不同node的相同结果,作为最终结果。

在详细解读之前,熟悉下几个概念:

(1) Check Point:检查点,是指当前节点处理的最新请求的编号,例如节点当前正在共识的请求的编号是100,那么对于该节点而言,其Check Point就是100;

 (2) Stable check point:稳定检查点,是指多数节点(2f + 1)已经共识完成的请求的最大编号。稳定检查点的主要作用就是减少内存占用,因为PBFT要求节点记住之前已经共识过的请求,随着时间推移,这些数据占用的内存会越来越多,因此需要有删除机制,删除的时候就可以把稳定检查点之前的请求全删掉(因为是大部分节点都已经共识过了的)。那怎么删呢?很简单,比如现在的稳定检查点是213,那么代表213号之前的记录已经共识过的了,所以之前的记录就可以删掉了。

  (3) 高低水位:假设当前的稳定检查点是100,则低水位h即为100,而高水位H = h + L,L是一个可设定的值。如果设定L为100,则高水位H就是200。例如某个A节点的当前请求编号是88,即checkpoint为88。而checkpoin 88 不在 [h,H] 区间内,那么这个88号请求将被无视。

下面来一张通用的图:

分布式一致性协议之 PBFT_第1张图片
 

上图中C为客户端,0 ~3 表示从节点,特别的,0为主节点,3 为故障节点。

1)客户端发送请求,激活主节点的服务操作。

2)当主节点接收请求后,启动三阶段的协议以向各从节点广播请求。

[2.1]Pre-Prepare:

主节点给 从客户端收到的请求分配编号,然后发出预准备消息<,message>给其他从节点。

view:当前视图的编号。视图的编号是什么意思呢?比如当前主节点为A,视图编号为1,如果主节点换成B,那么视图编号就为2.这个概念和raft的term任期是很类似的。

n:当前请求的编号。主节点收到客户端的每个请求都以一个编号来标记。

digest:消息内容的摘要

message:消息内容

只有满足以下条件,各个从节点才会接受一个预准备消息:

1、请求和预准备消息的签名正确,并且digest与message的摘要一致。
2、当前视图编号是v。
3、该从节点从未在视图v中接受过序号为n的消息,或者接受过但是摘要d和消息m需要和上次消息的一样。
4、编号n必须在高低水位h和H之间。

 

[2.2]Prepare:

从节点接收PRE-PREPARE消息,检查消息的合法性,通过检查后,向其他节点广播prepare消息,带上本节点的id,同时接受来自其他节点的PREPARE消息,收到PREPARE消息后同样进行合法性检查。一旦收到2f个不同节点的prepare消息,就代表prepare阶段已经完成。

只有满足以下条件,各个点才会接受一个准备消息:

1、消息的签名正确。

2、视图编号一致。

3、编号n满足高低水位。

 

[2.3]Commit:

广播commit消息,告诉其他节点某个提案n在视图v里已经处于准备状态,如果它收到了2f+1条commit消息(包括自身的一条,这些来自不同节点的commit消息携带相同的编号n和view v),则说明提案通过。该请求就会被节点执行。在完成请求的操作之后,节点向客户端发送回复。

只有满足以下条件,各个点才会接受一个确认消息:

1、消息的签名正确。

2、视图编号一致。

3、编号n满足高低水位。


3)客户端等待来自不同节点的响应,若有f+1个响应相同,则该响应即为运算的结果。

 

上面是主节点一切OK时的表现,但是如果主节点出了问题呢?为了解决主节点出问题的情况,PBFT引入了视图的概念。这个概念和raft的term任期是很类似的。可以理解为主节点的任期。

当主节点挂了(超时无响应)或者从节点集体认为主节点是问题节点时,就会触发ViewChange事件,ViewChange完成后,视图编号将会加1。

分布式一致性协议之 PBFT_第2张图片

如图所示,viewchange会有三个阶段,分别是view-change,view-change-ack和new-view阶段。

从节点认为主节点有问题时,会向其它节点发送view-change消息,当前存活的节点编号最小的节点将默认自己成为新的主节点。当新的主节点收到2f个其它节点的view-change消息,则证明有足够多的从节点认为主节点有问题,于是就会向其它节点广播New-view消息。从节点不会发起new-view事件。

对于新的主节点,其从它节点验证new-view消息通过后,就会处理新主节点发来的pre-prepare消息,这时执行的过程就是前面描述的pbft过程。到这时,正式进入 v+1(视图编号加1)的时代了。

总结

严格来说PBFT其实时paxos的一个变种。基于多段提交,多数节点表示可执行状态OK时,请求被执行。

你可能感兴趣的:(区块链)