Raft共识插件详解【Hyperledger Fabric】

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

Raft共识插件是在Hyperledger Fabric 1.4.1后引入的,与之前已有的Solo共识和Kafka共识相比,Raft共识更适合生产环境。本文将介绍共识的基本概念、Raft共识的原理并深入探讨基于Raft共识的
Hyperledger Fabric排序服务。

相关教程:

1、共识的基本概念

共识算法可以让机群协同工作,并且可以容忍部分成员主机的故障。通常我们提到主机的故障会区分两种情况对待:拜占庭故障和非拜占庭故障。

比特币是第一个解决了拜占庭故障的去中心化系统,它的方法是使用工作量证明共识(POW)。在一个存在拜占庭故障的系统中,不仅会发生主机崩溃的问题,而且某些成员可能会存在恶意行为去影响整个系统的决策过程。

如果一个分布式系统可以处理拜占庭故障,那么它就可以容忍任何类型的错误发生。常见的支持拜占庭故障的共识算法包括PoW、PoS、PBFT和RBFT。

Raft只能处理非拜占庭故障,也就是说Raft共识可以容忍系统崩溃、网络中断/延迟/包丢失等故障。常见的支持非拜占庭故障的共识算法或系统包括:Raft、Kafka、Paxos和Zookeeper。

那么,Hyperledger Fabric为什么不使用可以容忍拜占庭故障的共识机制呢?那样不是更安全吗?

一个原因在于系统的复杂性与安全性的设计折中。假设一个系统中可能同时有n个节点发生拜占庭故障,那么拜占庭容错要求系统至少有3n+1个节点存在。例如,为了应对100个潜在的恶意节点,你至少需要部署301个节点。这就让系统更复杂。Raft则只需要2n+1个节点来应对潜在的n个节点的非拜占庭故障,显然复杂性和成本要低一些。因此有些分布式系统还是更倾向于Raft,尤其是考虑到像Hyperledger Fabric这种许可制的联盟链环境中,通常会使用数字证书等安全机制来增强安全性,因此存在恶意节点的可能性很小。

2、Raft共识的基本原理

Raft是一个分布式崩溃故障容错共识算法,它可以保证在系统中部分节点出现非拜占庭故障的情况下,系统依然可以处理客户端的请求。从技术上来讲,Raft是一个管理复制日志(Replicated Log)的共识算法,复制日志是复制状态机(RSM:Replicated State Machine)的组成部分。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6zfgxWjR-1575531606072)(hyperledger-fabric-raft-impl/rsm-arch.png)\]

复制状态机是用于构建分布式系统的一种比较基础的架构。它的主要构成单元包括:包含命令序列的节点日志、共识模块(例如Raft)和状态机。

复制状态机的工作原理如下:

在这里插入图片描述

  1. 客户端向主导节点(Leader Node)发送包含命令的请求
  2. 主导节点将收到的请求追加到其日志中,并将该请求发送给所有的 跟随节点(Follower Node)。跟随节点也会将该请求追加到自身的日志中 并返回一个确认消息
  3. 一旦主导节点收到大部分跟随节点的确认消息,就会将命令日志提交给其管理的状态机。一旦主导节点提交了日志,跟随节点也会将日志提交给自身管理的状态机
  4. 主导节点向客户端返回响应结果

那么,Raft在复制状态机架构中扮演什么角色?

Raft的作用是确保跟随节点的日志与主导节点的日志保持一致(即:日志复制),这样整个分布式系统的行为看起来是一致的,即使部分节点出现故障也没有影响。

另一个问题,客户端是否需要了解哪个是主导节点?

答案是NO,客户端可以向任何一个节点发送请求,如果该节点是主导节点,那么它会直接处理请求,否则的话,该节点会转发请求给主导节点。

3、Raft共识的基本特性

3.1 Raft节点状态

对于Raft算法而言,每个节点只能处于三个状态之一:

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ody1jv2R-1575531606074)(hyperledger-fabric-raft-impl/raft-node-states.png)\]

跟随状态:初始情况下,所有的节点都处于跟随状态,也就是都是跟随节点。一旦某个跟随节点没有正常通信,它就转换为候选状态(Candidate),也就是成为一个候选节点。跟随节点的日志可以被主导节点重写。

候选状态:处于候选状态的节点会发起选举,如果它收到集群中大多数成员的投票认可,就转换为主导状态。

主导状态:处理客户端请求并确保所有的跟随节点具有相同的日志副本。主导节点不可以重写其自身的日志。

如果候选节点发现已经选出了主导节点,它就会退回到跟随状态。同样,如果主导节点发现另一个主导节点的任期(Term)值更高,它也会退回到跟随状态。

任期(Term)是一个单调递增的整数值,用来标识主导节点的管理周期。每个任期都从选举开始,直到下一个任期之前。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KZoF0Ca2-1575531606074)(hyperledger-fabric-raft-impl/term.jpg)\]

3.2 Raft主导节点的选举

Raft使用心跳机制来出发主导节点的选举。当节点启动后进入跟随状态,只要它能从主导节点或候选节点收到有效的RPC心跳消息,就会保持在跟随状态。主导节点会周期性发送心跳消息(没有日志项的AppendEntries RPC消息)给所有的跟随节点来维持其主导地位。如果某个跟随节点在一段时间内没有收到心跳消息,就发生选举超时事件,该节点就认为目前没有主导节点并发起选举来选出新的主导节点。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mjsbYjcq-1575531606074)(hyperledger-fabric-raft-impl/election.png)\]

要开始一个选举,跟随节点会递增其当前任期值并转换到候选状态。该节点首先给自己投一票,然后同时向其他节点发送请求投票的消息(RequestVote RPC消息)。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1GAd6m5N-1575531606075)(hyperledger-fabric-raft-impl/requestvote.png)\]

候选节点会保持在候选状态,直到以下事件发生:

  • 该节点胜出选举
  • 其他节点胜出选举
  • 没有节点胜出选举

如果该节点收到大部分节点的投票认可,就可以胜出选举,那么该节点就转换到主导状态成为新的主导节点。注意:每个节点只能投一票。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ss7fp012-1575531606075)(hyperledger-fabric-raft-impl/election-win.png)\]

如果同时也有其他节点宣布自己是主导节点并有更高的任期值,那么任期值高的节点成为新的主导节点:

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ucZm24Ql-1575531606076)(hyperledger-fabric-raft-impl/higher-term.png)\]

如果多个候选节点的得票情况相同,那么没有胜出节点。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jbWWb5yt-1575531606076)(hyperledger-fabric-raft-impl/split-vote.png)\]

要避免出现这种情况,可以重新初始化选举并确保每个节点的选举超时时长是随机的,以避免跟随节点同时进入候选状态。

3.3 日志复制

一旦选出主导节点,它就开始处理客户端的请求。请求中包含有复制状态机需要执行的命令。主导节点将命令追加到自己的日志中,然后并行发送AppendEntriesRPC消息给所有跟随节点复制这个新的日志项。当新的日志项被安全复制后,主导节点会在自身的状态机上执行这个日志项里的命令,并将结果返回给客户端。

如果跟随节点崩溃、运行缓慢或网络发生丢包问题,主导节点会无限重试发送AppendEntries RPC消息(即使它已经向客户端返回了响应结果),直到所有的跟随节点最终得到一致的日志副本。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qlRY1oKk-1575531606076)(hyperledger-fabric-raft-impl/log-replica.png)\]

当发送AppendEntries RPC消息时,主导节点会同时发送新日志项的前序日志项的序号和任期值。如果跟随节点在自身日志中没有发现相同的序号和任期值,就会拒绝新的日志项。因此如果pendEntries成功返回,主导节点就知道跟随节点的日志与自己是完全一致的。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YMRv2er3-1575531606077)(hyperledger-fabric-raft-impl/log-consistency-check.png)\]

当出现不一致情况时,主导节点强制跟随节点复制自己的日志。

4、Hyperledger Fabric的Raft排序服务实现

基于Raft的排序服务替代了之前的Kafka排序服务。每个排序节点都有其自己的Raft复制状态机来提交日志。客户端利用Broadcast RPC发送交易提议。Raft排序节点基于共识生成新的区块,当对等节点发送Deliver RPC时,将区块发送给对等节点。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vDESNlPu-1575531606077)(hyperledger-fabric-raft-impl/raft-osn.png)\]

Raft排序节点的工作流程如下:

  1. 交易(例如提议、配置更新)应当自动路由到通道的当前主导节点
  2. 主导节点检查交易验证的配置序列号是否与当前配置序列号一致,如果不一致的 话则执行验证,并在验证失败后驳回交易。通过验证后,主导节点将收到的交易传入区块切割模块的Ordered方法,创建候选区块
  3. 如果产生了新的区块,主导排序节点将其应用于本地的Raft有限状态机(FSM)
  4. 有限状态机将尝试复制到足够数量的排序节点,以便提交区块
  5. 区块被写入接收节点的本地账本

每个通道都会运行Raft协议的单独实例。换句话说,有N个通道的网络,就有N个Raft集群,每个Raft集群都有自己的主导排序节点。

5、基于Raft共识的Hyperledger Fabric网络实战

我们使用BYFN组件展示raft共识模块的使用方法。BYFN包含5个排序节点,2个组织4个对等节点,以及可选的CouchDB。在configtx.yaml文件中给出了Raft排序服务的配置。

用下面的脚本命令启动默认的go链码和raft共识,该脚本会自动生成必要的密码学数据:

cd fabric-samples/first-network
./byfn.sh up -o etcdraft

查看排序服务:

docker logs -f ordrer3.example.com

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Fhzeh18P-1575531606078)(hyperledger-fabric-raft-impl/raft-osn-screenshot.png)\]

现在我们验证Raft的容错能力。

首先停掉Node3:

docker stop orderer3.example.com

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SDqvxMQW-1575531606079)(hyperledger-fabric-raft-impl/node3-down.png)\]

然后停掉Node5:

docker stop orderer5.example.com

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oVlp6kN4-1575531606080)(hyperledger-fabric-raft-impl/node5-down.png)\]

现在验证系统的有效性,可以看到系统依然可以正常响应客户端的请求:

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U3xMcH7T-1575531606082)(hyperledger-fabric-raft-impl/cli-bash.png)\]
\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wm01DxOR-1575531606083)(hyperledger-fabric-raft-impl/cli-query.png)\]


原文链接:Hyperledger Fabric Raft共识深度解析 - 汇智网

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
开发框架 .NET 区块链
Hyperledger fabric部署链码(五)初始化与链码升级
fabric部署chaincode-go(智能合约)系列之五
208 0
|
测试技术 Go 区块链
Hyperledger fabric 测试环境部署
Hyperledger fabric 测试环境部署及相关问题解答
278 3
Hyperledger fabric 测试环境部署
|
JavaScript 测试技术 Go
Hyperledger fabric部署链码(一)打包链码
fabric部署chaincode-go(智能合约)系列之一
253 0
|
存储 JSON 安全
Hyperledger fabric智能合约编写(一)
本篇文章主要对链码编写的主要思路和部分API进行梳理。
177 1
|
区块链
Hyperledger fabric部署链码(二)安装链码到fabric
fabric部署chaincode-go(智能合约)系列之二
149 1
|
Go API 区块链
Hyperledger Fabric相关概念介绍
在学习Hyperledger Fabric的过程中,初步对相关概念的了解。
268 0
Hyperledger Fabric相关概念介绍
|
JSON 区块链 数据格式
Hyperledger fabric部署链码(四)提交链码定义到channel
fabric部署chaincode-go(智能合约)系列之四
|
测试技术 API 区块链
Hyperledger fabric部署链码(三)批准链码定义
fabric部署chaincode-go(智能合约)系列之三
137 0
|
消息中间件 Java Kafka
Hyperledger Fabric 通道配置文件和容器环境变量详解
Fabric 节点的主配置路径为 FABRIC_CFG_PATH 环境变量所指向路径(默认为 /etc/hyperledger/fabric)。在不显式指定配置路径时,会尝试从主配置路径下查找相关的配置文件。
361 0
|
安全 区块链 数据库
联盟链 Hyperledger Fabric 应用场景
本文主要通过一个例子分享以Hyperledger Fabric为代表的联盟链应用场景。
736 0
联盟链 Hyperledger Fabric 应用场景