前言

從數據庫的角度看待區塊鏈的存儲機制會簡單直觀很多。在一個標準的關係型數據庫中,存儲一般分爲日誌存儲、用戶數據存儲、以及索引存儲三大類(有些數據庫可能還包含大對象存儲等)。

而區塊鏈項目中基本所有的“賬本”存儲其本質就是交易日誌存儲。用戶數據存儲則根據項目不同而有選擇性地採用。譬如說對於 UTXO 結構的區塊鏈項目來說,其每個賬號對應的餘額直接保存在內存哈希表中(或類似 LevelDB 等嵌入式 KV 數據庫中),因此不需要一個獨立的外接用戶數據存儲模塊。而類似 Hyperledger 等通用區塊鏈框架則一般包含類似 State Store 等存儲最終結果數據的模塊。索引存儲則在當前大部分區塊鏈項目中均不存在。

1.賬本格式

區塊鏈的鏈式結構筆者在這裏不再贅述,其每個塊包含上一個塊的哈希值,而內容則使用默克爾樹進行校驗以實現快速驗證,每條記錄則使用數字簽名的方式保證其一定來自擁有私鑰的用戶。

1

圖 1:區塊鏈數據結構

對比傳統數據庫的日誌結構,區塊鏈結構並不複雜。一般來說,所有傳統數據庫日誌結構都比較相似,每個日誌文件包含日誌頭與多個日誌數據頁,其中日誌頭代表其起始交易號(Oracle 中叫做 SCN,DB2 中叫做 LSN),也就是該日誌文件中第一條日誌記錄在整個日誌空間中的起始字節數,以及日誌文件大小,日誌頁大小等元數據信息。緊接着真實的日誌記錄則以二進制碼流的方式依次存放在文件中,每一條日誌記錄頭包含該條記錄的交易號、事務號、同一事務中上一條記錄的交易號(反向指針),以及變更前與變更後的數據(滿足回滾要求)。

2

圖 2:數據庫日誌結構

因此,從結構上來看,區塊鏈賬本與數據庫日誌本質上沒有任何區別,僅僅在數據結構上爲了滿足一些特定要求做了部分優化。

2. 存儲內容

通用型數據庫與當前大部分區塊鏈賬本項目(例如比特幣、以太坊等,而 Hyperledger 這類區塊鏈平臺則不包含在內)從日誌的角度看,最大的區別在於區塊鏈賬本項目對於日誌格式進行了高度定製化與業務綁定。

一般來說,傳統的數據庫日誌包含的是數據頁的變更信息,我們叫做“寫前鏡像”和“寫後鏡像”,代表新的數據寫入前這條記錄長什麼樣子,同時新數據寫入後這個記錄長什麼樣子。通過這種方式,可以很輕易地在磁盤中的某個數據頁的指定偏移上進行數據前滾與回滾操作。

譬如說一條數據庫日誌並不會記錄一個 INSERT 操作的具體命令,而是以“X 數據頁的第 Y 個槽位,其所對應的偏移地址數據由 ABC 變化爲 DEF,總長度 Z”的方式體現出來。因此,數據庫的日誌幾乎可以記錄任何信息,這也是爲什麼通用數據庫可以被用來實現任何業務邏輯的原因。

而大部分的賬本項目則高度定製化其日誌結構,例如以太坊的每一條交易信息都會包含輸入金額、輸出金額、燃料等信息,然後每一個節點在進行驗證時必須判斷其符合某種規則,否則不予通過。這種機制可以看做是一個完全高度定製化的數據庫業務,每一條日誌記錄不僅僅記錄數據內容的變更,而是與業務邏輯緊密耦合,記錄每個賬戶的餘額變化。

因此,從可擴展性來看,儘管以太坊等項目支持“智能合約”,但是其核心本質還是一個高度定製化的賬本系統,其業務邏輯與交易結算進行了非常緊密的綁定。

3. 設計思路

從設計哲學上看,當前的區塊鏈與數據庫在對通用業務的支持上採用了兩種不同的策略。對於傳統數據庫來說,其秉承的設計理念是“業務與數據分離”的思路,也就是說數據庫僅負責數據的存放,通過提供一種靈活的查詢語言能夠讓應用程序直接訪問數據庫進行增刪改查,但是基本所有的業務邏輯由應用程序自行定義。

但是,對於區塊鏈來說則是存儲與業務邏輯緊耦合的思路。在區塊鏈,尤其是公鏈的設計哲學中,因爲每個存儲節點和應用都是不可信的,因此大部分業務邏輯需要在協議層進行高度定製。一個區塊鏈節點即需要對協議層進行解析和封裝,同時也需要負責對數據本地化落盤和存儲。

因而,儘管站在高層面可以將區塊鏈看做是多活數據庫,但是如果從具體實現層面來看,每個區塊鏈節點又不能簡單地看做是一個傳統數據庫的多活替代品,而是一套包含協議解析封裝和一部分業務邏輯的應用軟件。

4. 用戶數據存儲

如果未來區塊鏈的目標是作爲通用平臺,用以存儲多種類型的數據,則其日誌格式與存儲必須迴歸數據庫的通用性本源。當前的賬本模式可以作爲該體系中的一個特別模塊存在用以進行賬戶間結算,但是無法將其擴展爲通用業務平臺。

既然要成爲通用數據存儲平臺,那麼 UTXO 模型存在一定侷限性。在一個典型的銀行業務中,零售業務可能會包含千萬甚至億級別的賬戶,不同賬戶可能使用不同的利息計算規則,也可能存在凍結等特殊狀態。而交易流水信息每天可能達到千萬筆,如果將其業務擴展到非金融行業,流水信息每天幾億也是可能的。因此,從一個通用賬戶+流水的業務模型中,一般企業會建立一個賬戶表與一個流水錶,以不同的策略進行管理。

賬戶表俗稱餘額類數據,在典型的數據治理體系中需要做到定期快照備份(例如月初數和月末數);而流水錶則成爲流水類數據,一般來說以原始交易格式直接存儲和備份。通過對餘額類數據快照備份的恢復,對指定賬號重做某個時間範圍內的全部交易流水,可以得到該賬號任意時間點的餘額信息。

而 UTXO 的本質在於日誌存放的信息不是記錄的最終結果,而是變化行爲。在傳統數據庫中,每條事務記錄的是數據的寫前與寫後內容。例如將一條記錄從 5 更改爲 8,其數據庫日誌記錄原始數據爲 5 且新數據爲 8,而不是記錄“+3”的操作。但是 UTXO 記錄的是變更信息,其主要的目的是解決雙花問題(例如對於一個有 100 塊錢的賬號,一個人在中國轉走 10 塊錢,另一個人在美國同時轉走 10 塊錢,如果記錄的是最終結果,那麼中國的服務器會認爲這個人有 90 塊,美國的服務器在沒有全局鎖的情況下也會認爲這個人有 90 塊,最終寫到區塊中就變成 90 塊餘額,而非 80)。

UTXO 的機制可以有效地在無鎖的情況下避免雙花問題,但是其劣勢則在於不存儲餘額表,所有的信息均通過重做流水數據,從零開始生成。對於一個存在了十年以上,包含幾百億筆交易的系統來說,這樣的做法就好比每次重啓都要從都重做幾百筆交易並存入內存中(或 KV 數據庫裏),是一種非常原始且不經濟的方式。

另一方面,區塊鏈日誌的結構看來,由於多活系統中全局鎖很難實現,因此需要通過交易日誌結構的調整來滿足傳統數據庫中事務的功能。傳統數據庫中當涉及到兩賬戶之間轉賬操作時需要開啓一個事務。在事務日誌中一個賬戶增加一個賬戶減少的業務邏輯,需要體現爲包含三條記錄的鏈表(最後的提交操作也是一個記錄)。在數據庫崩潰或發生異常後,只要通過重做所有的任務,並最後對全部沒有提交記錄的事務進行反向操作,即可得到原子性(Atomic)與持久性(Durability)。

而在區塊鏈體系中由於不存在事務的概念,同時操作日誌與結算業務進行了緊密耦合,因此每條交易記錄都會包含一個輸入賬號以及若干個輸出賬號,也就是說只要一條事務記錄被成功發送給一個節點,則可以保證在該記錄內部的全部輸入輸出賬戶統一進行了變更。可以說,區塊鏈通過定製化交易日誌簡化了事務操作的複雜性,但是帶來的影響便在於業務與代碼的緊密耦合不可分割。

但是無論如何,首先 UTXO 並不是通用數據結構,而是爲交易業務高度定製化的數據結構,如果想要運行圖靈完備的智能合約(或者說存儲過程),使用 UTXO 會有很多侷限性。第二,對長期運行的大型系統(相比起大中型銀行核心交易系統所產生的交易流水,比特幣從誕生到現在的交易量少得可以忽略不計),UTXO 每次初始化需要全部的歷史交易日誌。這種模式完全不可能適用於大型交易系統。

因此,可以存在兩種做法解決該問題。第一種方式使用傳統賬戶表與流水錶的機制,將 UTXO 以流水的方式體現出來,同時定期保存賬戶快照,以避免每次重構數據庫都需要重做全部交易(這種機制需要考慮到賬戶與流水錶在多活系統中,沒有全局鎖的情況下如何實現一致性的問題)。而對於非結算類交易,通用型區塊鏈項目則可能採用日誌結合用戶數據存儲的模式,才能夠普適性地滿足通用業務需求(這種機制需要依靠比 nonce 更好的排序機制避免雙花)。

5. 索引存儲

當前基本沒有任何區塊鏈項目支持用戶數據的自定義索引。這種機制在未來的通用型區塊鏈項目一定會被彌補。從本質上看當前的區塊鏈項目結構沒有任何理由無法在其上構建通用索引能力(包括 B 樹索引、位圖索引、全文檢索等)。

小結

區塊鏈的存儲體系現在還處於數據庫上世紀 80 年代的階段,其當前最大的問題在於日誌結構與業務邏輯的緊密耦合(讀者可以理解爲應用程序爲每種業務邏輯都要從頭實現一遍 Oracle)。而這樣做的本質原因在於多活數據庫中事務的原子性與鎖極難保障,因此當涉及到多個賬戶的轉賬原子操作時,當前大部分賬本類區塊鏈項目均不得不定製日誌結構,將每一筆交易的全部信息放在一條記錄中。

從數據庫的角度看,在區塊鏈項目中實現跨記錄的原子操作(包括全局鎖)極爲複雜,而這也正式區塊鏈技術向通用型數據存儲進化的關鍵所在。

筆者認爲,隨着區塊鏈應用越發廣泛,人們在不久的將來一定會將各類區塊鏈應用泛化出一系列典型的場景和需求。基於這些場景和需求,一定會出現一批優秀高效的多活數據存儲。不論這些機制的後臺到底是否基於“區塊”的架構實現,其這正需要突破的是現有數據庫體系中無法做到 active-active 的侷限(也就是去中心化)。

發文時比特幣價格 ¥43378.32

作者:Jun Tang
編輯:野比大雄
稿源:巴比特資訊(http://www.8btc.com/blockchain-storage-mechanism) 版權聲明:
by
nc"
sa
作者保留權利。文章爲作者獨立觀點,不代表巴比特立場。

來源鏈接:www.8btc.com