PBFT共识算法 (2)

可以再想一个问题,此时可以直接执行请求吗?答案是不可以,因为此时,你只能确认自己收到了\(2f\)个一致的PREPARE消息,你无法确认其他节点是否也收到了\(2f\)个一致的PREPARE消息。也就是说,当前,你只能确认自己准备好了去执行序号为n的请求,但是你不能确认其他节点有没有准备好,所以,还要再进行一次节点间的消息交互,互相告诉大家,我准备好了。

COMMIT:

在上一阶段,节点收到足额PREPARE投票后会广播COMMIT投票,过程类似,当节点收到其他节点的COMMIT投票消息后,会进行如下检查:

消息合法性检查,检查消息签名是否正确,消息摘要正不正确有没有被篡改。

视图检查,view是否匹配。

水线检查,判断n是否在h和H之间。

如果都通过则把收到的投票消息写入日志log中,如果收到的合法的COMMIT投票消息大于等于\(2f+1\)个(包括自己),意思就是,已经确认大多数节点都准备好了执行请求,就执行请求并回复REPLY消息给客户端。这里如同上面一样,也是检查视图,序号及消息是否匹配。

REPLY:

客户端收到REPLY后,会进行统计,如果收到\(f+1\)个相同时间戳t和响应值r,则认为请求响应成功。如果在规定的时间内没有收到回应或者没有收到足额回应怎么办?可以将该请求广播给所有节点,节点收到请求后,如果该请求已经被状态机执行了,则再次回复客户端REPLY消息,如果没有被状态机执行,如果节点不是主节点,就将该请求转发给主节点。如果主节点没有正常的将该请求广播给其他节点,则将会被怀疑是主节点故障或恶意节点,当有足够的节点都怀疑时将会触发视图变更协议,更换视图。

我们进行进一步的分析,可以看到,如果是客户端没有收到任何回应,很有可能是主节点故障或主节点是恶意节点(我就故意不执行你的请求),没有将请求足额广播给其他节点,(当然还有消息丢失等原因,这里不在详细分析),这时,客户端因一直没有响应,所以将请求广播给了所有节点,所有节点收到请求后,转发给主节点后发现主节点怎么什么都不干呀,怀疑主节点有问题,然后触发视图更换协议,换掉主节点。当然,客户端没有收到足额回应的一个原因还可能是消息丢失,那么如果是已经执行了该请求的节点再次收到该请求后会再次回应REPLY,前提是该请求是在水线范围内的合法请求,否则被拒绝。

检查点协议

在上面的一致性协议中可以看到,系统每执行一个请求,服务器都需要记录日志(包括,request、pre-prepare、prepare、commit等消息)。如果日志得不到及时的清理,就会导致系统资源被大量的日志所占用,影响系统性能及可用性。另一方面,由于拜占庭节点的存在,一致性协议并不能保证每一台服务器都执行了相同的请求,所以,不同服务器状态可能不一致。例如,某些服务器可能由于网络延时导致从某个序号开始之后的请求都没有执行。因此,设置周期性的检查点协议,将系统中的服务器同步到某一个相同的状态。简言之,主要作用有2个:1、同步服务器的状态;2、定期清理日志。

同步服务器的状态,比较容易理解与做到。比如在区块链系统中,同步服务器的状态,实际上就是追块,即服务器节点会通过链定时广播的链世界状态或其他消息获知到自己区块落后了,然后启动追块流程。

定期清理日志,怎么做呢?首先要明确哪些日志可以被清理,哪些日志仍然需要保留。如果一个请求已经被\(f+1\)台非拜占庭节点执行,并且某一服务器节点i可以向其他服务器节点证明这一点,那么该i节点就可以将关于这个请求的日志删除。协议一般采用的方式是服务器节点每执行一定数量的请求就将自己的状态发送给所有服务器并且执行一个该协议,如果某台服务器节点收到\(2f+1\)台服务器节点的状态,那么其中一致的部分就是至少有\(f+1\)台非拜占庭服务器节点经历过的状态,因此,这部分的日志就可以删除,同时更新为较新状态。

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

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