1. 程式人生 > >使用Merkle樹檢測資料不一致(翻譯)

使用Merkle樹檢測資料不一致(翻譯)

背景

Cassandra的逆熵功能使用Merkle樹來檢測副本之間的資料不一致。

定義

Merkle樹是一種雜湊樹,其中的葉子包含各個資料塊的雜湊值,父節點包含其各自的子節點的雜湊值。它提供了一種有效的方法來查詢副本上儲存的資料塊中的差異,並減少了傳輸以比較資料塊的資料量。

Cassandra的Merkle樹(org.apache.cassandra.utils.MerkleTree)的實現使用完美的二叉樹,其中每個葉子都包含行值的雜湊,每個父節點都包含其左右子節點的雜湊。在一棵完美的二叉樹中,所有葉子都處於同一水平或相同深度。深度為h的完美二叉樹包含2 ^ h樹葉。換句話說,如果範圍包含n個標記,則表示該範圍的Merkle樹包含log(n)級別。

執行nodetool repair命令時,在命令中用-h選項指定的目標節點會協調每個鍵空間中每個列系列的修復。修復協調器節點從每個副本請求Merkle樹以獲取特定的令牌範圍,以對其進行比較。每個副本通過掃描在請求的令牌範圍內本地儲存的資料來構建Merkle樹。修復協調器節點比較Merkle樹,找到所有副本之間不同的子令牌範圍,並修復這些範圍內的資料。

複製節點為每個列族構建一個Merkle樹,以表示給定令牌範圍內的行的雜湊。使用RandomPartitioner時,令牌範圍最多可以包含2 ^ 127個令牌。需要深度為127的Merkle樹,其中包含2 ^ 127個葉子。Cassandra構建了深度為15的Merkle樹的緊湊版本,以減少用於儲存樹的記憶體使用量,並最小化將Merkle樹傳輸到另一個節點所需的資料量。它將擴充套件樹,直到將給定的令牌範圍劃分為32768個子範圍。在樹的緊湊版本中,每個葉子表示其各自子範圍中所有行的雜湊。無論其大小和拆分程度如何,如果兩棵Merkle樹具有相同的雜湊深度,就可以對其進行比較。

例如,令牌範圍(0,256]包含256個子範圍(0,1],(1,2] ...(255,256],每個包含單個令牌。深度為8的完美二叉樹需要在葉子上儲存所有256個子範圍雜湊。深度為3的同一版本的樹的緊湊版本僅包含8個代表子範圍(0,32],(32,64] ...(224,256]子集雜湊的葉子包含32個令牌。在此緊湊型樹中,每個葉雜湊是深度為8的理想二叉樹中其下所有節點的計算雜湊。

構建Merkle樹(遞迴)

RandomPartitioner均勻地分配key,因此通過將給定標記範圍分成兩個相等的子範圍,直到達到最大子範圍數,從而遞迴構造Merkle樹。將根節點新增給定的令牌範圍(左,右),並在令牌的範圍內將其分為兩半,令牌位於範圍的中點。左側的子節點新增範圍(左,中點)和在右邊的子節點上新增範圍覆蓋(中點,右邊),重複此過程,直到將所需數量的葉子(子範圍)新增到樹上為止。

將下一行雜湊按排序順序新增到Merkle樹中。通過計算行值的MD5摘要來計算每行的雜湊值,該值包括行的列數,列名和列值,但不包括行鍵和行大小。刪除的行(邏輯刪除)雜湊也會新增到樹中,其中包括刪除時間戳。行雜湊基於其令牌新增到Merkle樹葉。如果葉子的子範圍包含多行,則使用XOR操作通過組合其範圍所覆蓋的所有行的雜湊來計算其雜湊。非葉節點雜湊值是通過對各自子節點的雜湊值執行XOR計算得出的。

比較默Merkle樹(遞迴)

如果兩棵Merkle樹都覆蓋相同的令牌範圍,則無論它們的大小如何,都將對其進行比較。從根雜湊開始遞迴比較樹。如果兩個樹中的根雜湊都匹配,則樹的令牌範圍中的所有資料塊在副本之間都是一致的。如果根雜湊不一致,則比較左子雜湊,然後再比較右子雜湊。進行比較,直到計算出兩棵樹之間的所有令牌範圍都不同為止。

Q&A

Q:如何保證節點儲存的token範圍都是一致的??
A:因為Cassandra的複製節點是順時針進行制定的,複製的數量由複製因子決定,而比較就發生這些節點之間

小結

Merkle樹不僅可以快速比較 多個檔案是否完全相同,而且如果不同可以快速定位到不相同的檔案

參考

http://distributeddatastore.blogspot.com/2013/07/cassandra-using-merkle-trees-to-detect.h