Cassandra的逆熵功能使用Merkle樹來檢測副本之間的數據不一致。html
Merkle樹是一種哈希樹,其中的葉子包含各個數據塊的哈希值,父節點包含其各自的子節點的哈希值。它提供了一種有效的方法來查找副本上存儲的數據塊中的差別,並減小了傳輸以比較數據塊的數據量。node
Cassandra的Merkle樹(org.apache.cassandra.utils.MerkleTree)的實現使用完美的二叉樹,其中每一個葉子都包含行值的哈希,每一個父節點都包含其左右子節點的哈希。在一棵完美的二叉樹中,全部葉子都處於同一水平或相同深度。深度爲h的完美二叉樹包含2 ^ h樹葉。換句話說,若是範圍包含n個標記,則表示該範圍的Merkle樹包含log(n)級別。apache
執行nodetool repair命令時,在命令中用-h選項指定的目標節點會協調每一個鍵空間中每一個列系列的修復。修復協調器節點從每一個副本請求Merkle樹以獲取特定的令牌範圍,以對其進行比較。每一個副本經過掃描在請求的令牌範圍內本地存儲的數據來構建Merkle樹。修復協調器節點比較Merkle樹,找到全部副本之間不一樣的子令牌範圍,並修復這些範圍內的數據。dom
複製節點爲每一個列族構建一個Merkle樹,以表示給定令牌範圍內的行的哈希。使用RandomPartitioner時,令牌範圍最多能夠包含2 ^ 127個令牌。須要深度爲127的Merkle樹,其中包含2 ^ 127個葉子。Cassandra構建了深度爲15的Merkle樹的緊湊版本,以減小用於存儲樹的內存使用量,並最小化將Merkle樹傳輸到另外一個節點所需的數據量。它將擴展樹,直到將給定的令牌範圍劃分爲32768個子範圍。在樹的緊湊版本中,每一個葉子表示其各自子範圍中全部行的哈希。不管其大小和拆分程度如何,若是兩棵Merkle樹具備相同的哈希深度,就能夠對其進行比較。htm
例如,令牌範圍(0,256]包含256個子範圍(0,1],(1,2] ...(255,256],每一個包含單個令牌。深度爲8的完美二叉樹須要在葉子上存儲全部256個子範圍散列。深度爲3的同一版本的樹的緊湊版本僅包含8個表明子範圍(0,32],(32,64] ...(224,256]子集散列的葉子包含32個令牌。在此緊湊型樹中,每一個葉哈希是深度爲8的理想二叉樹中其下全部節點的計算哈希。blog
RandomPartitioner均勻地分配key,所以經過將給定標記範圍分紅兩個相等的子範圍,直到達到最大子範圍數,從而遞歸構造Merkle樹。將根節點添加給定的令牌範圍(左,右),並在令牌的範圍內將其分爲兩半,令牌位於範圍的中點。左側的子節點添加範圍(左,中點)和在右邊的子節點上添加範圍覆蓋(中點,右邊),重複此過程,直到將所需數量的葉子(子範圍)添加到樹上爲止。排序
將下一行哈希按排序順序添加到Merkle樹中。經過計算行值的MD5摘要來計算每行的哈希值,該值包括行的列數,列名和列值,但不包括行鍵和行大小。刪除的行(邏輯刪除)哈希也會添加到樹中,其中包括刪除時間戳。行哈希基於其令牌添加到Merkle樹葉。若是葉子的子範圍包含多行,則使用XOR操做經過組合其範圍所覆蓋的全部行的哈希來計算其哈希。非葉節點哈希值是經過對各自子節點的哈希值執行XOR計算得出的。遞歸
若是兩棵Merkle樹都覆蓋相同的令牌範圍,則不管它們的大小如何,都將對其進行比較。從根哈希開始遞歸比較樹。若是兩個樹中的根哈希都匹配,則樹的令牌範圍中的全部數據塊在副本之間都是一致的。若是根哈希不一致,則比較左子哈希,而後再比較右子哈希。進行比較,直到計算出兩棵樹之間的全部令牌範圍都不一樣爲止。token
Q:如何保證節點保存的token範圍都是一致的??
A:由於Cassandra的複製節點是順時針進行制定的,複製的數量由複製因子決定,而比較就發生這些節點之間內存
Merkle樹不只能夠快速比較 多個文件是否徹底相同,並且若是不一樣能夠快速定位到不相同的文件
http://distributeddatastore.blogspot.com/2013/07/cassandra-using-merkle-trees-to-detect.html