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

爲了校驗每個數據塊,咱們須要對每一個數據塊作哈希,造成一個哈希列表,這樣進行下載前,咱們先要獲取一個哈希列表,下載後,咱們就可以經過哈希列表,來驗證每個數據塊。哪怎麼保證這個哈希列表是正確的呢,或者說怎麼校驗完整數據呢?只要每個數據塊哈希是正確的,最終獲取的完整數據就必定是正確的,因此,咱們須要對哈希列表進行哈希獲得根哈希,將此根哈希放到一個可信源中,在下載數據前,先從可信數據源哪裏獲取到數據的跟哈希,而後從任意機器獲取哈希列表,再下載數據塊。這樣,數據完整性能夠經過根哈希來保證。code

Merkle tree 對比 Hash list

兩種數據結構都有驗證數據完整性的功能,均可以經過根哈希保證總體數據完整性。所不一樣的是,在數據龐大,數據塊很是多的狀況下,當根哈希檢測到數據不一致時,Merkle tree能夠快速的定位到致使不一致的數據塊,複雜度爲O(log(n)),而Hash list只能遍歷龐大的哈希列表定位到致使不一致的數據塊,複雜度爲O(n),很顯然,此時Merkle tree的效率要高不少。blog

參考文檔:Hash list

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

相關文章
相關標籤/搜索