拜占庭容错的基本思想和基本过程(算法)

以下内容并非原创,转载整理自:
[1] 知乎:如何通俗的理解IBM区块链技术HyperLedger/fabric中的共识算法PBFT(拜占庭容错)? 作者:蒋雨辰
[2] 《区块链原理、技术与应用》杨保华 陈昌 等著

拜占庭容错基本思想

概览

拜占庭容错是一种共识算法,即如何使远距离通信的人们对一个提案达成一致意见。

与普通的共识算法(例如,majority wins,即超过一半人赞成即有效)不同的是,PBFT可以容忍投票的人中产生叛徒或者不响应。

举个例子

我是一个愚昧的国王,没有自己的判断力,我不知道应该对敌国进攻还是投降好。我有一些大臣,我希望听从他们的意见做出决定,但是他们现在都离我很远,我只能通过飞鸽传书的方式告知他们目前的问题,得到他们的选择。然而,可能出现大臣叛变,故意提出相反的观点(错误的节点),也可能出现鸽子在传输过程中飞错了,我没有得到该大臣的选择(网络堵塞)。PBFT可以保证如果我有3f+1的大臣的话,即使其中有f个大臣叛变或者没有响应,我依然可以得出共识的正确结果。

为什么是3f+1?

为什么有f个节点未响应或出错时,为了保证系统的正常,我需要总共有3f+1个节点进行投票。

同样用国王的例子,假设除了我(国王)一共有n个大臣,我知道其中有f个大臣是叛徒或者未响应,所以我一定要能从n-f个大臣的回应中进行判断(如果上述f个大臣都是未响应)。然而由于是飞鸽传书(异步传输),所以当我陆续收到n-f个传来的消息后,我并不知道之后是否还会有新的消息传来。因为如果f个有问题的大臣都是未响应,那么我将不会收到新的消息,如果其中有大臣是叛徒,我之后还会收到消息,但作为国王的现在不知道是哪种情况,却需要立刻作出进攻还是投降的判断。

最坏的情况下,剩下的f个大臣都是好人,只是鸽子飞得慢我还没收到消息,也就是说我收到消息的n-f的大臣中有f个大臣都是叛徒,即f个叛徒和n-2f个好人。由于多数者胜,所以只有当n-2f>f的情况下,作为国王的我会做出正确的决定,即n>3f,n最小需要取3f+1。

这也就是为什么PBFT能保证有3f+1节点投票时,允许f个节点未响应或者出现故障投相反票。

拜占庭容错基本过程(算法)

算法整体的基本过程如下:

  • 首先,通过轮换或随机算法选出某个节点为主节点,此后只要主节点不切换,则称为一个视图(View)。
  • 在某个视图中,客户端将请求 <REQUEST,operation,timestamp,client> 发送给主节点,主节点负责广播请求到所有其它副本节点。
  • 所有节点处理完成请求,将处理结果 <REPLY,view,timestamp,client,id_node,response> 返回给客户端。客户端检查是否收到了至少 f+1 个来自不同节点的相同结果,作为最终结果。

主节点广播过程包括三个阶段的处理:预准备(Pre-Prepare)、准备(Prepare)和提交(Commit)。预准备和准备阶段确保在同一个视图内请求发送的顺序正确;准备和提交阶段则确保在不同视图之间的确认请求是保序的。
拜占庭容错

  • 预准备阶段:主节点为从客户端收到的请求分配提案编号,然后发出预准备消息 <<PRE-PREPARE,view,n,digest>,message> 给各副本节点,其中 message 是客户端的请求消息,digest 是消息的摘要。
  • 准备阶段:副本节点收到预准备消息后,检查消息。如消息合法,则向其它节点发送准备消息 <PREPARE,view,n,digest,id>,带上自己的 id 信息,同时接收来自其它节点的准备消息。收到准备消息的节点对消息同样进行合法性检查。验证通过则把这个准备消息写入消息日志中。集齐至少 2f+1 个验证过的消息才进入准备状态。
  • 提交阶段:广播 commit 消息,告诉其它节点某个提案 n 在视图 v 里已经处于准备状态。如果集齐至少 2f+1 个验证过的 commit 消息,则说明提案通过。
    具体实现上还包括视图切换、checkpoint 等机制,读者可自行参考论文内容,在此不再赘述。

拜占庭容错类的算法因为要考虑最恶意的存在“捣乱”者的情况,在大规模场景下共识性能往往会受到影响。


更多精彩内容