1. 程式人生 > >查詢--深入理解一致性雜湊演算法

查詢--深入理解一致性雜湊演算法

注:本篇部落格只是講述了一致性雜湊的思想,我們會在之後講述分散式雜湊表以及一致性雜湊的一種實現(Chord演算法)。

什麼是一致性雜湊演算法?

引用自維基百科:

一致性雜湊是一種特殊的雜湊演算法。在使用一致雜湊演算法後,雜湊表槽位數(大小)的改變平均只需要對 K/n個關鍵字重新對映,其中K是關鍵字的數量,n是槽位數量。然而在傳統的雜湊表中,新增或刪除一個槽位幾乎需要對所有關鍵字進行重新對映。

總結:一致性雜湊演算法主要關注的是在分散式架構中,當節點數目發生變化的時候(增加/刪除),怎樣使再雜湊的資料量最少。

一致性雜湊的引出

在分散式系統中,節點的宕機、某個節點加入或者移出叢集是常事。對於分散式儲存而言,假設儲存叢集中有10臺機器(node),如果採用傳統Hash方式對資料分片(item)(即資料根據雜湊函式對映到某臺機器上儲存),雜湊函式應該是這樣的:hash(item) % 10。根據上面的介紹,當node數發生變化(增加、移除)後,資料會被重新“打散”,導致大部分資料不能落到原來的節點上,從而導致大量資料需要遷移,而這種移動會造成網路的負載。

那麼,一個亟待解決的問題就變成了:當node數發生變化時,如何保證儘量少引起遷移呢?即當增加或者刪除節點時,對於大多數item,保證原來分配到的某個node,現在仍然應該分配到那個node,將資料遷移量降到最低。

一致性雜湊的原理及優劣

此處輸入圖片的描述

傳統的Hash演算法將對應的key雜湊到一個具有2^32次方(int)個桶的空間中,即0~(2^32)-1的數字空間中。現在我們可以將這些數字頭尾相連,想象成一個閉合的環形。也就是將傳統的線性雜湊表構造成環形雜湊表。

我們來看一下如何將資料對映到環形雜湊表上:

如上圖,有三臺機器(node),四個資料項(item),每臺機器對應著一個n位的ID(採用機器的IP或者機器唯一的別名作為雜湊函式的輸入值),並且對映到環中,每個查詢鍵,也是一個n位的ID,節點的ID和查詢鍵對應著相同的對映空間。三臺機器將整個環分割成了三部分,分別是(1,3),(3,2),(2,1)。

機器1負責儲存落在(2,1)範圍內的資料,機器2負責儲存落在(3,2)範圍內的資料…..

也就是說,對資料進行Hash時,資料的地址會落在環上的某個點上,資料就儲存在該點的順時針方向上的那臺機器上

這種資料儲存的方式,相比於普通雜湊方式,有明顯的優勢:當新增新機器或者刪除機器時,不會影響到全部資料的儲存,而只是影響到這臺機器上所儲存的資料(落在這臺機器所負責的環上的資料)。

而這種思想,也就是一致性雜湊。我們舉個例子來感受一下使用一致性雜湊的好處:

比如,機器1被移除了,那落在(2,1)範圍內的資料全部需要由機器3來儲存,也就隻影響到落在(2,1)這個範圍內的資料。同時,擴容也很方便,比如在(1,3)這段環上再新增一臺機器4,只需要將3上的一部分資料拷貝到機器4上即可。

雖然一致性Hash演算法解決了節點變化導致的資料遷移問題,但是,我們回過頭來再看看資料分佈的均勻性:

此處輸入圖片的描述

資料被傳統的雜湊演算法“打散”後,是可以比較均勻分佈的。但是引入一致性雜湊演算法後,為什麼就不均勻呢?資料本身的雜湊值並未發生變化,變化的是判斷資料雜湊後應該落到哪個節點的演算法變了。

這三個節點Hash後,在環上分佈不均勻,導致了每個節點實際佔據環上的區間大小不一,資料隨機對映到每個節點的概率就有較大差別,換個說法,也就是不能實現較好的負載均衡。

舉個例子:機器1的配置很高,效能很好,而機器3的配置很低。但是,如上圖,大部分資料由於某些特徵都雜湊到(1,3)這段環上,直接就導致了機器3的儲存壓力很大。

虛擬節點的引入

當我們將node進行雜湊後,這些值並沒有均勻地落在環上,因此,最終會導致,這些節點所管轄的範圍並不均勻,最終導致了資料分佈的不均勻。

為了解決一致性雜湊的不足,從而引入了虛擬節點的概念。

引入虛擬節點,可以有效地防止物理節點(機器)對映到雜湊環中出現不均勻的情況。比如上圖中的機器1、2、3都對映在環的左半邊上。

一般,虛擬節點會比物理節點多很多,並可均衡分佈在環上,從而提高負載均衡的能力。

此處輸入圖片的描述

  1. 如果虛擬節點與物理機器對映得好,某一臺物理機器宕機後,其上的資料可由其他若干臺物理機器共同分擔;
  2. 如果新新增一臺機器,它可以對應多個不相鄰環段上的虛擬節點,從而使得Hash的資料儲存得更分散。

如何判定一致性雜湊演算法的好壞?

  1. 平衡性(Balance):平衡性是指雜湊的結果能夠儘可能分佈到所有的緩衝(伺服器節點)中去,這樣可以使得所有的緩衝空間都得到利用,很多雜湊演算法都能夠滿足這一條件;
  2. 單調性(Monotonicity):單調性是指如果已經有一些內容通過雜湊分派到了相應的緩衝中,又有新的緩衝加入到系統中,雜湊的結果應能夠保證原有已分配的內容可以被對映到原有的或者新的緩衝中去,而不會被對映到舊的緩衝集合中的其他緩衝區;
  3. 分散性(Spread):在分散式環境中,終端有可能看不到所有的緩衝,而是隻能看到其中的一部分。當終端希望通過雜湊過程將內容對映到緩衝上時,由於不同終端所見的緩衝範圍有可能不同,從而導致雜湊的結果不一致,最終的結果是相同的內容被不同的終端對映到不同的緩衝區中。這種情況顯然是應該避免的,因為它導致相同內容被儲存到不同緩衝中去,降低了系統儲存的效率。分散性的定義就是上述情況發生的嚴重程度。好的雜湊演算法應能夠儘量避免不一致的情況發生,也就是儘量降低分散性;
  4. 負載(Load):負載問題實際上是從另一個角度看待分散性問題。既然不同的終端可能將相同的內容對映到不同的緩衝區中,那麼對於一個特定的緩衝區而言,也可能被不同的使用者對映為不同的內容。與分散性一樣,這種情況也是應當避免的,因此好的雜湊演算法應能夠儘量降低緩衝的負荷。

:對於第四點來說,好的一致性雜湊演算法,應該將同一使用者的請求對映到相同的機器上,因為一個緩衝區始終處理同一個使用者的請求是比較容易實現的(Cookie),如果將不同使用者的不同請求對映到相同的緩衝區中,既有可能增大機器的負載,而且不容易實現。

總結

  1. 熟悉一致性雜湊演算法的特點及原理;
  2. 熟悉一致性雜湊演算法的優劣與改進(虛擬節點);
  3. 掌握為什麼會出現一致性雜湊演算法;
  4. 瞭解一致性雜湊演算法的另一種改進(線性空間的引入)—詳見一致性雜湊演算法的理解與實踐

參考閱讀