Merkle樹


在分布式系統、P2P應用中或者是區塊鏈中,會經常使用一種數據結構Merkle tree(默克爾樹),這里我們將詳細討論一下這個常用數據結構。

Merkle tree

Merkle樹看起來非常像二叉樹,其葉子節點上的值通常為數據塊的哈希值,而非葉子節點上的值,所以有時候Merkle tree也表示為Hash tree,如下圖所示:

image

在構造Merkle樹時,首先要對數據塊計算哈希值,通常,選用SHA-256等哈希算法。但如果僅僅防止數據不是蓄意的損壞或篡改,可以改用一些安全性低但效率高的校驗和算法,如CRC。然后將數據塊計算的哈希值兩兩配對(如果是奇數個數,最后一個自己與自己配對),計算上一層哈希,再重復這個步驟,一直到計算出根哈希值。

Merkle樹大多用來進行完整性驗證,比如分布式環境下,從多台主機獲取數據,怎么驗證獲取的數據是否正確呢,只要驗證Merkle樹根哈希一致,即可。例如,下圖中L3數據塊發生錯誤(比如數據被修改了),錯誤會傳導到計算hash(L3),接着傳導到計算hash(Hash1-0+Hash1-1),最后傳導到根哈希,導致根哈希的不一致,可以說,任何底層數據塊的變化,最終都會傳導到根哈希。另外如果根哈希不一致,也可以通過Merkle樹快速定位到導致不一致的數據。

Merkle樹還可以用來對數據進行快速比對,快速定位到不一致的數據。比如分布式存儲中,一份數據會有多個副本,並且分布在不同的機器上。為了保持數據一致性,需要進行副本同步,而首要的就是比對當前副本是否一致,如一致,則無需同步,如不一致,還需找出不一致的地方,然后進行同步。很明顯,如果采用直接傳輸數據進行比對,非常低效,一般采用對數據進行哈希,傳輸哈希值進行對比的方法。為此,可以對每台機器需要比對的數據構造Merkle樹,如果根哈希一致,則數據相同,如果根哈希不一致,則通過Merkle樹快速檢索到不一致的數據。下面舉例說明快速檢索的過程,如上圖藍色標注所示。假設兩台機器中L3數據塊不一致,我們對比根哈希,發現根哈希不一致,即,數據不一致,此時需要找出是那一塊不一致,分別對比Hash0Hash1,發現是Hash1不一致,接着向下發現是Hash1-0不一致,這樣就定位到是L3數據塊不一致。定位過程的算法復雜度為O(log(n))

還有一種數據結構,在一定程度上可以看做是Merkle樹的子樹,但又不完全一樣,這個數據結構是Hash list(為了避免中文哈希列表與哈希表的誤解,這里使用英文名稱),我們下面看一下這個Hash list。

Hash list

在點對點網絡中數據傳輸的時候,為了提高效率往往會同時從多個機器下載數據的不同部分,即,不是從一台機器下載整個數據,而是將完整數據分成不同的部分,分別同時從不同的機器獲取完整數據的不同組成部分。這樣分塊傳輸不但可以同時從多台機器下載數據,另一個好處是如果這一小塊數據傳輸過程中損壞了,只要重新下載這一小數據塊就可以了,不用重新下載整個數據。

但這種分布式環境下,很多機器應該認為是不穩定或者不可信的,如何校驗整個數據的完整性及每一小數據塊的完整性呢?

image

為了校驗每一個數據塊,我們需要對每個數據塊做哈希,形成一個哈希列表,這樣進行下載前,我們先要獲取一個哈希列表,下載后,我們就能夠通過哈希列表,來驗證每一個數據塊。哪怎么保證這個哈希列表是正確的呢,或者說怎么校驗完整數據呢?只要每一個數據塊哈希是正確的,最終獲取的完整數據就一定是正確的,所以,我們需要對哈希列表進行哈希得到根哈希,將此根哈希放到一個可信源中,在下載數據前,先從可信數據源哪里獲取到數據的跟哈希,然后從任意機器獲取哈希列表,再下載數據塊。這樣,數據完整性可以通過根哈希來保證。

Merkle tree 對比 Hash list

兩種數據結構都有驗證數據完整性的功能,都可以通過根哈希保證整體數據完整性。所不同的是,在數據龐大,數據塊非常多的情況下,當根哈希檢測到數據不一致時,Merkle tree可以快速的定位到導致不一致的數據塊,復雜度為O(log(n)),而Hash list只能遍歷龐大的哈希列表定位到導致不一致的數據塊,復雜度為O(n),很顯然,此時Merkle tree的效率要高很多。

參考文檔:Hash list

關注微信公眾號,與我一起學習分布式、數據結構、區塊鏈!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM