Fabric2.x中Raft共識演算法核心資料結構

JasonCeng發表於2023-02-04

一、共識演算法可插拔的程式碼體現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共識演算法啟動流程進行分析。

相關文章