PBFT算法原理

引言———分布式系统一致性问题

区块链系统,首先是一个分布式系统。传统单节点结构演变到分布式系统,碰到的首要问题就是一致性的保障。很显然,如果分布式集群无法保证处理结果一直的话,那任何建立于其上的业务系统都无法正常工作。 一致性问题是分布式领域最为基础也是最重要的问题。如果分布式系统能实现“一致”,对外就可以呈现一个完美的、可扩展的“虚拟节点”,相对于物理节点具有更优越性能和稳定性。这也是分布式系统希望能实现的最终目标。在理想的情况下,如果各个服务节点严格遵守相同的处理协议,构成相同的处理机状态机,给定相同的初始状态和输入序列,则可以保证在处理过程中的每个环节的结果都是相同的。这里需要注意的是,我们所说的一致性并不代表结果正确与否,而是系统对外呈现的状态一致与否;例如,所有节点都达成失败状态也是一种一致。

一致性的问题和挑战

我们在涉及区块链的问题时,共识(consensus)在很多时候会与一致性(consistency)术语放在一起讨论。其实,两者的含义却是不同的。一致性往往指分布式系统中多个副本对外呈现的数据状态。它含有顺序一致性和线性一致性等等。描述了多个节点对数据状态的维护能力。而共识则描述了则描述了分布式系统多个节点之间,彼此对某个状态达成一致结果的过程。因此,一致性描述的是结果,共识则是一种手段,达成某种共识并不意味着就保障了一致性。 在实践中,要保障满足系统满足不同程度的一致性,核心过程往往需要通过共识算法来达成,共识算法解决的是对某个提案(propasal)大家达成一致意见的过程。如果分布式系统中各个单节点都能保证一十分理想的性能(如可以瞬间响应、超高吞吐)无故障地运行,节点之间通信瞬时送达,则实现共识过程并不十分复杂,简单地通过广播进行瞬时投票和应答即可。但实际上,现实种这样的“理想”系统并不存在。不同节点之间通信存在延迟,并且任意环节都可能存在故障(系统越大,出现故障的可能越大)。如通信网络会发生发生中断,节点会发生故障、甚至存在恶意节点故意要伪造消息,破坏系统的正常工作流程。 一般地,我们把出现故障(crash或fail-stop,即不响应)但不会伪造信息的情况成为“非拜占庭错误”(non-byzantine fault)或“故障错误”(Crash Fault);伪造信息恶意响应的情况成为“拜占庭错误”(Byzantine Fault),对应节点为拜占庭节点。

拜占庭问题与算法

拜占庭问题相对非拜占庭问题更为广泛,谈论的是允许存在少数节点作恶(消息可以被伪造)场景下的一致性达成问题。拜占庭容错(BFT)算法讨论的是在拜占庭情况下对系统如何达成共识。

1.两将军问题
在拜占庭将军问题之前,就已经存在两将军问题:两个将军问题需要信使来达成进攻还是撤退的约定,但信使可能迷路或者被敌军阻(消息丢失或伪造),如何达成一致性,这个问题无通用解。

2.拜占庭问题
拜占庭问题是Leslie Lamport等科学家在1982年提出用来解释一致性问题的一个虚构模型。拜占庭是古罗马的首都,守卫边境的多个将军(系统多个节点)需要通过信使来传递消息,达成某些一致的决定。但由于将军中可能存在叛徒(系统中节点出错),这些叛徒将努力向不同将军发送不同的消息,试图干扰共识达成。拜占庭问题即为在此情况下,如何让忠诚的将军能达成成功的一致。科学家在论文中提出,对于拜占庭问题来说,假如节点总数为N,叛变将军数为F,则当N>=3F+1时,问题才有解。

PBFT共识算法

拜占庭容错算法(BFT)是面向拜占庭问题的容错算法,解决的是在玩过通信中可靠但节点可能故障情况下如何达成共识。在1999年,Castro和Liskov提出的PBFT是第一个得到广泛应用的BFT算法。在PBFT算法中,至多可以容忍不超过系统全部节点数量的三分之一的拜占庭节点“背叛”,即如果超过三分之二的节点正常,整个系统就可以正常工作。 PBFT算法采用密码学相关技术(RSA签名算法、消息验证编码和摘要)确保消息过程中无法被篡改和破坏。算法的基本过程如下:

1.首先通过轮换或随机算法选出某个节点为主节点,此后只要主节点不切换,则成为一个视图(view)

2.在某个试图中,客户端将请求<Request,operation,timestamp,client>发送给主节点,主节点负责广播请求到所有其他副本节点。

3.所有节点处理完成请求,将处理结果<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消息,则说明提案通过。

下面通过一个实例来说明PBFT的基本过程,首先放一张在PBFT算法介绍中都能看到的图
在这里插入图片描述
从图中,结合区块链的角度来说明: C我们认为是客户端,0、1、2、3是分布式系统中的节点成员,0是主节点、1、2是备份节点,3也是备份节点但已发生故障,默认3发送信息为无效。

1.C发起一笔请求到0号主节点。

2.主节点0开始对请求排序编号,并把请求序号发送到1、2、3节点。

3.1、2节点互相之间和0主节点之间发送消息。

4.0、1、2之间确认0主节点的分配序号,互相确认。

5.0、1、2确认信息回复C。

6.客户端C判断收到确认是否在f1内,确认结果。

三个阶段达成共识:Pre-Prepare、Prepare 和 Commit,整个流程如下:

1.从全网节点选举出一个主节点(Leader),新区块由主节点负责生成。

2.每个节点把客户端发来的交易向全网广播,主节点将从网络收集到需放在新区块内的多个交易排序后存入列表,并将该列表向全网广播。

3.每个节点接收到交易列表后,根据排序模拟执行这些交易。所有交易执行完后,基于交易结果计算新区块的哈希摘要,并向全网广播。

4.如果一个节点收到的2f(f为可容忍的拜占庭节点数)个其它节点发来的摘要都和自己相等,就向全网广播一条commit消息。

5.如果一个节点收到2f+1条commit消息,即可提交新区块及其交易到本地的区块链和状态数据库。

PBFT算法存在的问题以及解决思路

拜占庭问题之所以难以解决,在于任何时候系统中都可能存在多个提案(因为提案成本很低),并且要完成最终一致性确认过程十分困难,容易受到各种因素的干扰。我们可以从两个环节进行改进:首先,限制一段时间内整个网络中出现提案个数(通过增加提案的成本);其次是放宽对最终一致性确认的需求,设定每个节点都确认并沿着在整个网络中最长的链进行拓展。系统的最终确认是概率意义上的存在。这样,即使有人试图恶意破坏,也会付出响应的经济代价(超过整个系统一半的算力)。或者沿着这个思路进行改进,采用经济上的惩罚来制约破坏者。

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值