Merkle樹

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章