胡 錦 玲
(廣州城建職業學院,510925,廣州)
隨著Hyperledger Fabric區塊鏈系統涉及的技術多樣且架構復雜[1]。區塊鏈(BlockChain)是一種具有去信任、去中心化、不可篡改、公開透明等特性的新興技術。在各個主流區塊鏈技術中,Hyperledger Fabric由Linux Foundation于2015年發起[2],Hyperledger Fabric 是分布式賬本解決方案的平臺,采用模塊化架構,提供高安全性、彈性、靈活性和可擴展性。目前已有包括IBM、Intel、百度等各大互聯網公司在內的200余個成員,著力于發展跨行業的企業級區塊鏈的研究,也是時下火熱的區塊鏈技術之一[3]。Hyperledger Fabric不僅支持Java、Go、Node.js在內的常見的編程語言用于智能合約的開發,同時不需要使用基于加密貨幣的共識機制來激勵昂貴的挖礦或智能合約的執行,從而大大降低了系統的運營成本。
在使用Hyperledger Fabric進行業務系統開發的過程中,不可避免地涉及到對鏈上數據的讀取和搜索。但是,由于區塊鏈的技術特性,對區塊鏈的數據讀取需要遍歷整個區塊鏈鏈條才能計算存儲數據的當前狀態。盡管Hyperledger Fabric通過內置了LevelDB、CouchDB等數據庫存儲WorldState的方式在一定程度上解決了區塊鏈數據的讀取問題[4-5],但這種方式面對業務系統中高頻且形式復雜的數據訪問,在功能和性能上顯然力有不逮。因此,在業務開發中通常還需要將鏈上數據同步寫入第3方數據存儲中,進而由其解決數據的讀取和搜索問題。這就需要應用開發者來解決區塊鏈及第3方數據存儲間的數據一致性問題。
為了支持以同樣的方式更新信息,并實現一整套賬本功能(交易,查詢等),區塊鏈使用智能合約來提供對賬本的受控訪問。本文旨在針對Hyperledger Fabric鏈上數據和第3方數據存儲間的數據同步問題,設計并實現了Hyperledger Fabric數據協同中間件,確保兩者間的安全數據同步,從而降低開發者的開發成本,提高開發效率。
Hyperledger Fabric支持多鏈[6]。在Hyperledger Fabric中,數據存儲一共包括4個部分:賬本數據、狀態數據庫、歷史記錄數據庫、區塊索引數據庫,如圖1所示。其中,賬本數據以二進制文件的形式保存了區塊鏈上每個區塊的具體數據。狀態數據庫則有LevelDB和CouchDB兩種實現形式,用于存儲賬本中每個數據項的最新值,方便鏈碼執行時快速調用。歷史記錄數據庫需要通過配置項開啟,開啟后在LevelDB中保存數據項的版本變化,即哪些區塊中的交易變更了數據項的值。區塊索引數據庫存儲了區塊文件的索引指針,以便快速找到對應的區塊文件。

圖1 Hyperledger Fabric數據存儲示意圖
Hyperledger Fabric的這些設計很好地滿足了數據的簡單讀寫需求,但對于實際應用中形式更加復雜的數據搜索條件則力有不逮。在很多現實場景中,用戶需要對數據進行更復雜的數據分析,例如在電子存證場景中,用戶可能希望以上傳用戶和上傳時間為搜索條件對存證進行搜索。而基于KV數據庫設計的狀態數據存儲顯然難以應對這種關系型數據庫擅長處理的查詢請求。而在一些情況下,應用系統還可能需要區塊鏈上的數據來生產數據報表或進行大數據分析,而需要將區塊鏈數據同步到HBase和Hive這樣擅長處理海量數據的存儲中。因此,出于應用系統運行過程中高頻且形式復雜的數據讀取搜索和數據分析的需要,開發中通常需要將區塊鏈中存儲的數據同步到第3方存儲中,通過第3方存儲來實現復雜的數據搜索需求,并提高系統性能。在這種情況下,如何保證兩者間數據同步過程中的數據一致性是需要重點解決的問題。為了解決這個問題,本文設計并實現了可插拔的Hyperledger Fabric數據協同中間件,以保證Hyperledger Fabric區塊鏈與第3方存儲間的安全數據同步。
通常用戶對Hyperledger Fabric聯盟鏈中的數據修改通過調用鏈碼提交交易的方式實現。而用戶發出的交易提案首先需要發送到Peer節點,由Peer節點調用鏈碼并對該提案背書,進而提交到排序節點,再經由排序節點驗證和排序后才能成功寫入區塊并下發給Peer節點,最后由Peer節點驗證并寫入各自持有的賬本[4]。從用戶提交交易提案到數據寫入賬本的調用鏈路漫長,如果同步等待區塊鏈的鏈碼調用結果則會因為漫長的交易提交過程占用大量系統資源。同時,數據上鏈的過程中還有因為網絡波動或交易沖突等多種原因失敗的風險,在客戶端發出交易提案的同時直接將數據寫入第3方存儲可能導致數據上鏈失敗卻在第3方存儲中寫入成功,因此還需要考慮數據上鏈失敗條件下的數據回滾或重試機制,邏輯將變得臃腫而復雜。
相比之下,選擇異步的將已經確認寫入Hyperledger Fabric賬本中的數據同步到第3方存儲,則可以節省大量因同步等待而消耗的資源,邏輯也更加簡單直接。在Hyperledger Fabric聯盟鏈中,提供了基于通道的Peer節點事件服務,在應用程序在對應通道注冊監聽器后,每當通道中有新區塊產生,該服務都會發送一個事件到監聽應用程序中,事件中以envelope的形式包含了具體的區塊消息。
因此,在具體實現上,數據協同中間件選擇通過監聽Hyperledger Fabric區塊鏈網絡中Peer節點廣播的新增區塊消息的方式來異步獲取新增區塊的數據,進而分析區塊中打包的交易及讀寫集數據。最后,使用消息隊列將交易對賬本數據的更新通知到第3方存儲。在這個過程中,仍需要考慮由于網絡的不確定性和系統的偶然崩潰等意外導致的數據缺失或數據重復的情況,并考慮對應的手段來確保數據的一致性和消息的冪等性。在此基礎上,數據協同中間件的同步工作流程見圖2。

圖2 數據同步訪問控制流程圖
實現數據協同訪問控制策略,從圖2中可以看到,數據在由區塊鏈同步到第3方存儲的過程中,主要經過了2次數據傳輸。第1次是從Peer節點通過廣播消息的方式,由區塊鏈傳輸到數據協同中間件;第2次是由數據協同中間件交至消息隊列,通知第3方存儲寫入數據。由于在每個系統內部可以通過單機事務的方式確保操作的原子性,因此這2次數據傳輸是最容易發生數據丟失風險的步驟。
經過分析,可能導致產生數據不一致風險的具體原因如下。
1)數據協同中間件監聽區塊鏈數據變更的方式是監聽Peer節點發送的區塊新增事件,如果由于網絡波動或中間件服務器宕機等原因導致監聽事件的丟失,將會導致數據不一致。
2)數據協同中間件收到區塊鏈系統發出的消息后,通知第3方存儲寫入數據的消息丟失。
3)第3方存儲數據寫入成功后,數據協同中間件沒有收到確認,重復發送消息導致數據重復寫入。在數據協同中間件中,對于問題1),使用了CheckPoint機制記錄區塊的處理進度,在發生消息丟失時自動要求Peer節點重發丟失消息;對于問題2),數據協同中間件通過消息隊列傳遞消息,并使用重試機制確保消息在傳遞過程中不會丟失;對于有問題3),則需要第3方存儲在收到消息后,通過本地消息表的方式來確保消息的冪等性。
數據協同中間件通過監聽Peer節點廣播的事件消息的形式獲取區塊鏈中新增區塊的具體信息,進而通過分析得到具體交易的讀寫集。在監聽消息的過程中,可能由于消息丟失、處理異常等原因導致數據出現不一致。因此,數據協同中間件通過CheckPoint機制來確保不會遺漏處理消息,且在數據處理過程中即使發生崩潰異常也能保證數據一致。具體過程如下。
1)在監聽到事件消息后,CheckPoint首先會對比收到消息中的區塊高度和已同步的區塊高度,確認是否存在遺漏的消息。如果存在則會通知Peer節點重發遺漏消息記錄。
2)如果不存在遺漏消息,則會在數據庫中保存新收到的消息,避免后續處理失敗時反復要求Peer節點重放事件消息。在保存時會判斷消息記錄表中是否已經有相同區塊高度且狀態為待處理或處理成功的區塊消息,如果有則保存失敗,流程結束。CheckPoint保存區塊消息的記錄表結構見表1。

表1 CheckPoint區塊消息記錄表
3)如果區塊消息記錄成功,則解析消息的具體內容,得到區塊中打包的所有交易及其讀寫集。
4)通過交易讀寫集獲取數據變更項,通過消息隊列發送給第3方存儲。
5)消息如果發送成功則在記錄表中更新其處理狀態為處理成功;否則,重試發送消息。
通過CheckPoint機制和消息隊列,數據協同中間件能夠保證將Hyperledger Fabric區塊鏈中寫入的數據以消息的形式安全地順序交付給第3方存儲。值得注意的是,為了確保發給第3方的消息不會丟失,數據協同中間件在消息隊列中配置了重試機制,消息的接收方在成功消費消息后會自動發回一條Ack確認消息,如果生產者沒有收到Ack消息,則會在設定的重試間隔后重新向消費者發送消息。
因此,第3方存儲在成功消費消息并寫入數據后,向消息隊列發回的Ack確認消息也有可能因為網絡波動原因丟失,從而導致觸發重試機制,消息被重復消費。在這種情況下,需要由消息的消費者保證消息的消費冪等性。一個可行的保證消息消費冪等性的方法是通過一張額外的數據表記錄消息的消費狀態[7],如果發現重復消息則不寫入數據。由于消息隊列中的消息ID可能發生重復,而在Hyperledger Fabric的場景下,每一筆交易都會擁有一個唯一的交易ID。因此可以通過交易ID標記消息是否已經被成功消費,避免數據的重復消費。記錄消息消費狀態的本地消息表結構見表2。

表2 本地消息表
部署數據協同中間件后,通過鏈碼向Hyperledger Fabric區塊鏈網絡提交交易寫入數據,中間件能夠成功接收到Hyperledger Fabric發出的廣播消息,并將數據寫入第3方存儲中。結果如圖3所示。

圖3 數據同步效果圖
隨后斷開數據協同中間件到Hyperledger Fabric網絡的連接,并繼續向Hyperledger Fabric提交交易,模擬廣播消息遺失的情況。在恢復網絡連接后,可以看到中間件在收到新的區塊廣播消息時,會自動向Hyperledger Fabric請求遺失的消息,如圖4。

圖4 遺失消息效果圖
本文從區塊鏈數據協同訪問控制策略的中間件設計與研究,分析了Hyperledger Fabric中數據存儲的形式,在此基礎上設計并實現了Hyperledger Fabric數據協同中間件,實現了Hyperledger Fabric和第3方存儲間的自動化數據同步,提高開發效率。在此基礎上,通過CheckPoint
機制避免遺漏廣播消息導致的數據丟失,通過本地消息表避免數據的重復寫入,有效地確保兩者間的數據一致性。