概述
超級賬本1.0的架構,將節點進行了拆分,分為endorser、orderer和committer三類節點,節點各司其職。其中orderer節點負責共識,目前從官方文檔看,支持Solo(單節點共識)、kafka(分布式隊列)和SBFT(簡單拜占庭容錯)三種共識方式。本文主要介紹基于kafka實現的共識機制。
設計思路
kafka是一個分布式高可用消息隊列,可以有序的管理消息并在多個冗余副本間保證數據一致性。kafka集群的狀態由zookeeper管理,選舉leader節點。
orderer服務從kafka集群里獲取相應topic(kafka的分區,用于在隊列里隔離出多個數據域)的數據,以保證交易數據有序,借助了kafka的分布式一致機制。如下圖:
這樣的設計有一系列的問題需要考慮。
問題1
orderer服務(OSN)為每一筆交易進行驗證和出塊,效率不高。
改進
kafka里的交易數據按批次出塊,減少驗證次數,設置batchSize。
問題2
出塊是異步且批量的,如果交易到達速度不平均,batchSize可能很久未到達,影響出塊時間。
改進
為了降低批次的等待,設置出塊的時間batchTimeout,超時或達到批次上限,均會觸發出塊操作。
問題3
不同的OSN-n的時間很難同步,導致各OSN出塊所包含的交易會不一致。
改進
各OSN增加出塊協熵消息(TTC-n,TimeToCut),并將該消息上送至kafka,以第一個TTC-n為準出塊,后續重復的TTC-n將被忽略,以達到一致。
問題4
OSN根據塊高度同步數據,但塊高度和kafka的offset沒有關聯上,無法識別kafka的斷點位置。
改進4-a
使用塊的metadata域存儲offset,如:“offsets:63-64”。
不足1):與Deliver接口不一致,需要增加塊高度參數。
不足2):OSN丟失了若干塊,如果從一個隨機塊或最新塊開始同步,它將無法識別正確的offset。
改進4-b
每個OSN針對每條鏈都要維護一個檢索表,記錄了塊高度和offset的對應關系,而不需要使用塊的metadata數據。
問題5
每個OSN在收到分發請求后,都要從當前的節點進行追數,每個節點都要進行相同的操作,而且該操作的代價比較昂貴。
改進5-a
再創建一個分區,用于記錄OSN提交的塊,可以冗余且無序。但會引發問題6。
改進5-b
持久化已生成的塊數據,每個OSN本地存儲一個日志記錄。同時解決了問題6。
問題六
kafka中存在冗余的消息;檢索表會被請求,分發請求處理邏輯相對復雜,檢索表操作會增加等待時間。
改進6-a
如果OSN收到唯一的消息,并且自己即將處理相同的消息,則立刻終止自己的提交操作。這樣可以大量減少冗余數據提交,但不能完全消除。
改進6-b
選舉一個OSN的leader (ZK或誰產生TTC-x誰是主) ,由它負責分區1上下一個塊數據的產生。但是仍然可能出現冗余數據:主節點提交塊X后宕掉,此時選舉出新的主節點,它判斷塊X仍未提交,所以將自己的塊X提交,此時原主節點的數據也提交至kafka上,出現冗余數據。
改進6-c
kafka記錄壓縮,用kv結構存儲??梢酝耆龜祿哂鄦栴},但由于kv數據以最后提交的為準,會導致檢索表數據過時。
改進6-d
因為改進5b方案,本地賬本解決了冗余塊消息的問題。
引用
《A Kafka-based Ordering Service for Fabric》 by Kostas Christidis