1. 程式人生 > >分散式一致性hash演算法

分散式一致性hash演算法

寫在前面

  在學習Redis的叢集內容時,看到這麼一句話:Redis並沒有使用一致性hash演算法,而是引入雜湊槽的概念。而分散式快取Memcached則是使用分散式一致性hash演算法來實現分散式儲存。所以就專門學習了一下

什麼是分散式?什麼是一致性?什麼是雜湊?

  1)分散式(distributed)是指在多臺不同的伺服器中部署不同的服務模組,通過遠端呼叫協同工作,對外提供服務。“分散式一致性hash演算法”中的“分散式”就是指快取資料的分佈性

  這裡寫圖片描述

  這裡寫圖片描述

  集中式將一個系統的所有服務模組部署到了不同的伺服器上,構成一個叢集,通過負載均衡裝置對外提供服務

。集中式部署就像茶水間同時有多個飲水機提供服務,服務冗餘部署。分散式部署則將系統拆分成不同的服務模組,然後將不同的服務模組部署在不同的伺服器上。

  2)一致性Wiki的定義:

  Consistent hashing is a special kind of hashing such that when a hash table is resized, only K/n keys need to be remapped on average, where K is the number of keys, and n is the number of slots. In contrast, in most traditional hash tables, a change in the number of array slots causes nearly all keys to be remapped because the mapping between the keys and the slots is defined by a modular operation.

  大概意思就是“一致性雜湊是一種特殊的雜湊演算法,提供了這樣的一個雜湊表,當重新調整大小的時候,平均只有部分(k/n)key需要重新對映雜湊槽,而不像傳統雜湊表那樣幾乎所有key需要需要重新對映雜湊槽”。一致性hash能保證在分散式環境中,對key進行雜湊的結果或者說key與節點之間的對映關係不會受節點的增加和刪除而產生重大的變化

  3)hash,俗稱“雜湊”,也叫雜湊,是一種將任意長度的訊息(資料)壓縮到某一固定長度的訊息摘要(資料)的演算法。常見的hash演算法有MD5,SHA等。hash演算法具有幾個重要的特性:不可逆性(即從hash值反推出原訊息是不可能的)、抗衝突性(即給定訊息M1,不存在另一個訊息M2,使得Hash(M1)=Hash(M2))和分佈均勻性

(即hash的結果是均勻分佈的)。Memcached中,存取資料時都要進行雜湊對映。正是這幾個特性,保證了memcached快取中key值得唯一性

分散式一致性hash演算法使用背景

  我們已經知道,memcached的分散式主要在於客戶端的分散式演算法。memcached客戶端就像一個網路中的路由,經過特定的演算法將資料分散的存在到memcached服務端的機器上,又從分散的memcached服務端的機器上提取資料。實際中,常見的儲存和提取資料的演算法有取模演算法和本文分析的一致性hash演算法

  取模演算法演算法的原理是:

hash(key)%N

  其中key 代表資料的鍵,N 代表memcached伺服器的數量。取模的結果就是memcached客戶端要定位的memcached伺服器。取模演算法很明顯,結果受N的影響,當伺服器數量N增加或者減少的時候,原先的快取資料定位幾乎失效,快取資料定位失效意味著要到資料庫重新查詢,這對於高併發的系統來說是致命的。於是,人們提出了一致性hash演算法,最終目的是實現在移除、新增一個memcached伺服器時對已經存在的快取資料的定位影響儘可能的降到最小。

環形hash空間

  通常,一個快取資料的key經過hash後會得到一個32位的值,也就是0~2^32 - 1數值範圍。我們可以把這個數值範圍抽象成一個首尾相連環形的空間,我們稱這個空間為環形hash空間。如下圖所示:

  這裡寫圖片描述

對映key、server節點到環形hash空間

  有了環形hash空間之後,快取資料的key經過hash後得到的值就對映到了環形hash空間。假設有key1、key2、key3、key4,經過hash後,對映到環形hash空間如下圖所示。同理,我們可以把memcached伺服器抽象成網路上的節點經過hash後對映到環形hash空間。假設有server1(可以是伺服器的某些唯一標誌資訊,如ip等)、server2、server3

  這裡寫圖片描述

對映key到server節點

  現在快取key和server節點都經過一致性hash演算法對映到了環形hash空間,現在就可以將快取key和server節點的關係進行映射了。順時針沿著環形hash空間,從某個快取key開始,直到遇到一個server節點,那麼該快取key就儲存到這個server節點上。如圖:

  這裡寫圖片描述

  瞭解了key、server節點、hash空間之間的對映關係之後,已經清楚了快取資料是怎樣分佈的儲存到memcached伺服器了。查詢快取資料的時候,也採用同樣的對映方法來定位。

刪除server節點

  當在server叢集中刪除server2節點時,受影響的也僅是server1~server2之間的快取資料Key3,這部分資料需要重新到資料庫查詢再次對映到server3節點上。如下圖所示:

  這裡寫圖片描述

新增server節點

  現在我們已經知道memcached儲存和訪問資料的策略了。那麼當在server叢集中增加一個server節點時,對資料訪問的命中率又有什麼影響呢。如下圖,在server1和server2節點之間增加一個節點server4

  這裡寫圖片描述

  從上圖可以看出,增加server4節點後,原有的快取資料分佈中,僅有server1和server4節點之間的資料進行了重新分佈,這部分資料需要重新到資料庫查詢再次對映到新新增的server4節點上。儘管不能命中的快取資料仍然存在,但相對於取模演算法,已經是最大限度地抑制了hash鍵的重新分佈。

虛擬節點的引入

  我們已經知道,新增和刪除節點都會影響快取資料的分佈。儘管hash演算法具有分佈均勻的特性,但是當叢集中server數量很少時,他們可能在環中的分佈並不是特別均勻,進而導致快取資料不能均勻分佈到所有的server上

  為解決這個問題,需要使用虛擬節點的思想:為每個物理節點(server)在環上分配100~200個點,這樣環上的節點較多,就能抑制分佈不均勻。當為cache定位目標server時,如果定位到虛擬節點上,就表示cache真正的儲存位置是在該虛擬節點代表的實際物理server上。另外,如果每個實際server節點的負載能力不同,可以賦予不同的權重,根據權重分配不同數量的虛擬節點。

  虛擬節點的hash計算可以採用對應節點的 IP 地址加數字字尾的方式。例如假設 serverA 的 IP 地址為 127.0.0.1 。

  引入虛擬節點前,計算serverA 的 hash 值:

hash(“127.0.0.1”);

  引入虛擬節點後,計算虛擬節點serverA1 和 serverA2 的 hash 值:

hash(“127.0.0.1#1”);  
hash(“127.0.0.1#2”);

一致性hash演算法與取模演算法的比較

  取模演算法的方法簡單,資料的分散性也可以,但其主要缺點是當新增或移除server節點時,快取重新對映的代價相當巨大。新增或移除server節點時,餘數就會產生鉅變,這樣就無法定位與儲存時相同的server節點,從而影響快取的命中率。

  而一致性hash演算法則最大限度的減少了server節點變化帶來的影響,當節點變化時,隻影響一個server節點的部分資料,且hash演算法能夠保證需要重新分佈的快取資料能對映到新的server節點中。

如果您覺得這篇文章對您有所啟發、有所幫助,可以給我打賞一元錢,去買個茶葉蛋吃,謝謝~~~~

微信:

這裡寫圖片描述

支付寶:

這裡寫圖片描述

—–樂於分享,共同進步,歡迎補充
—–Any comments greatly appreciated
—–誠心歡迎各位交流討論!QQ:1138517609