Fabric2.x中Raft共识算法核心数据结构

一、共识算法可插拔的代码体现Chain接口

Hyperledger Fabric的共识算法是可插拔的,在代码上体现为Chain接口,所有不同的共识算法均可根据Chain接口进行具体实现,目前fabric支持solo、kafka、raft、sbft等共识算法。Chain接口的代码在fabric/orderer/consensus/consensus.go中

// Chain定义了为ordering注入messages的方式,这种设计允许如下两种流程: // 1.消息被排序为流,流被切割成块,块被提交(solo,kafka) // 2.消息被切成块,块被排序,然后块被提交(sbft) type Chain interface { 	// 排序函数,env是交易信息,configSeq是自增序号,每次有配置更新时都会+1,以确保交易是在最新的config下进行 	Order(env *cb.Envelope, configSeq uint64) error  	// 处理配置交易,提交后更新configSeq 	Configure(config *cb.Envelope, configSeq uint64) error  	// 超过max in-flight限制的消息会被阻塞,等待in-flight先执行完 	WaitReady() error  	// 当发生error时,会返回一个空channel 	Errored() <-chan struct{}  	// 分配与Chain保持最新数据的资源 	Start()  	// 刷新分配给Chain的资源 	Halt() } 

二、Fabric的raft共识算法Chain结构体

Hyperledger Fabric对Raft算法的核心实现代码都是放在fabric/orderer/consensus/etcdraft包下的,这里主要包含几个核心的数据结构,即Chain结构体和node结构体。

Chain结构体实现了Chain接口,代码位于orderer/consensus/etcdraft/chain.go,它里面主要定义了一些通道(channel)用于节点间的通信,以便根据通信消息做相应的操作。 // Chain implements consensus.Chain interface. type Chain struct {    configurator Configurator    rpc RPC // 节点与外部节点进行通信的对象,RPC 是一个接口,包含两个方法SendConsensus 和 SendSubmit。前面这种用于节点间 raft 信息的通讯,后者用于转发交易请求给 leader 节点。    raftID    uint64    channelID string    lastKnownLeader uint64    ActiveNodes     atomic.Value    submitC  chan *submit // 接收 Orderer 客户端提交的共识请求消息的通道    applyC   chan apply // 接收 raft 节点间应用消息的通道    observeC chan<- raft.SoftState    haltC    chan struct{}             doneC    chan struct{}     startC   chan struct{}     snapC    chan *raftpb.Snapshot //接收 raft 节点快照数据的通道    gcC      chan *gc     …    Node *node // fabric封装了底层 etcdraft 库的节点实例    … } 

三、Fabric的raft共识算法node结构体

node结构体封装了底层ercdraft库的节点实例,代码位于orderer/consensus/etcdraft/node.go,主要用于将Fabric自己实现的Raft上层应用和etcd的底层Raft实现连接起来,可以说node结构体是它们之间通信的桥梁,正是它的存在屏蔽了Raft实现的细节。

type node struct { 	chainID string 	logger  *flogging.FabricLogger 	metrics *Metrics 	unreachableLock sync.RWMutex 	unreachable     map[uint64]struct{} 	tracker *Tracker 	storage *RaftStorage 	config  *raft.Config 	rpc RPC 	chain *Chain // fabric自己定义的Chain结构体,具体在orderer/consensus/etcdraft/chain.go中 	tickInterval time.Duration 	clock        clock.Clock 	metadata *etcdraft.BlockMetadata 	subscriberC chan chan uint64 	raft.Node // raft底层的Node接口 } 

四、小结

Fabric的raft共识算法通过Chain结构体实现可插拔的共识算法Chain接口;又通过node结构体,实现对etcdraft底层算法实现细节的封装。Chain结构体和node结构体是承上启下的一层,fabirc的raft共识算法启动、交易处理流程均围绕上述两个结构体进行。下一篇博客将围绕fabric的raft共识算法启动流程进行分析。

发表评论

相关文章