分佈式一致性hash算法簡介

分佈式一致性hash算法簡介

當你看到“分佈式一致性hash算法”這個詞時,第一時間可能會問,什麼是分佈式,什麼是一致性,hash又是什麼。在分析分佈式一致性hash算法原理之前,我們先來了解一下這幾個概念。

分佈式

分佈式(distributed)是指在多臺不同的服務器中部署不同的服務模塊,通過遠程調用協同工作,對外提供服務。

現有系統system,有modelA、modelB、modelC等服務模塊。現在要以集中式(集羣,cluster)和分佈式的方式進行部署,下面我們來看看它們部署的示意圖。

wps25B9.tmp

集中式示部署意圖

wps25CA.tmp

圖分佈式部署示意圖

從上面的集中式示部署意圖和分佈式部署示意圖中我們可以看出,集中式將一個系統的所有服務模塊部署到了不同的服務器上,構成一個集羣,通過負載均衡設備對外提供服務。集中式部署就像茶水間同時有多個飲水機提供服務,服務冗餘部署。分佈式部署則將系統拆分成不同的服務模塊,然後將不同的服務模塊部署在不同的服務器上。

從上圖我們也可以看出,分佈式部署方案中,不僅僅是分佈式服務,還有分佈式數據存儲、分佈式靜態資源,分佈式計算等。此時,可能你已經回憶起上提到的,memcached不就是一套分佈式的緩存系統嗎。對,沒錯,memcached的分佈式就體現在分佈式數據存儲,“分佈式一致性hash算法”中的“分佈式”就是指緩存數據的分佈性。

一致性

瞭解了分佈式之後,一致性就好理解了。有分佈式數據存儲數據,那就離不開分佈式提取數據。一致性hash能保證在分佈式環境中,對key進行哈希的結果或者說key與節點之間的映射關係不會受節點的增加和刪除而產生重大的變化。參考wiki中一致性hash的定義:

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,俗稱“哈希”,也叫散列,是一種將任意長度的消息(數據)壓縮到某一固定長度的消息摘要(數據)的算法。常見的hash算法有MD5,SHA等。hash算法具有幾個重要的特性:不可逆性(即從hash值反推出原消息是不可能的)、抗衝突性(即給定消息M1,不存在另一個消息M2,使得Hash(M1)=Hash(M2))和分佈均勻性(即hash的結果是均勻分佈的)。memcached中,存取數據時都要進行哈希映射。正是這這幾個特性,保證了memcached緩存中key值得唯一性。

三個詞已經介紹完了,那memcached爲什麼要使用分佈式一致性hash算法呢,繼續看下文。

回到頂部

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

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

取模算法算法的原理是:

hash(key)%N

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

分佈式一致性hash算法的簡介和使用背景已經介紹完了,想必你對“分佈式一致性hash算法”這個詞已經不陌生了,下面將開啓我們的”分佈式一致性hash算法”原理的講解。

回到頂部

環形hash空間

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

 

圖 環形hash空間

 

映射key到環形hash空間

有了環形hash空間之後,緩存數據的key經過hash後得到的值就映射到了環形hash空間。假設有key1、key2、key3、key4,經過hash後,映射到環形hash空間如下圖所示:

 

圖 key映射到環形hash空間

映射server節點到hash空間

同理,我們可以把memcached服務器抽象成網絡上的節點經過hash後映射到環形hash空間。假設有server1(可以是服務器的某些唯一標誌信息,如ip等)、server2、server3,經過hash後,映射到環形hash空間如下圖所示:

 

圖 server節點映射到環形hash空間

映射key到server節點

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

 

圖 key映射到server節點

瞭解了key、server節點、hash空間之間的映射關係之後,現在我們已經清楚了緩存數據是怎樣分佈的存儲到memcached服務器了。查找緩存數據的時候,也採用同樣的映射方法來定位。

添加server節點

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

 

圖 增加server4節點

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

 

刪除server節點

同理,當在server集羣中刪除server2節點時,受影響的也僅是server1~server2之間的緩存數據,這部分數據需要重新到數據庫查找再次映射到server3節點上。如下圖所示:

圖 刪除server2節點

 

虛擬節點的引入

我們已經知道,添加和刪除節點都會影響緩存數據的分佈。儘管hash算法具有分佈均勻的特性,但是當集羣中server數量很少時,他們可能在環中的分佈並不是特別均勻,進而導致緩存數據不能均勻分佈到所有的server上。還有就是負載不均衡的問題,當Node3加到Node2和Node1之間時,原本會訪問Node1的緩存數據有50%的概率會緩存到Node3上了,這樣Node0和Node2的負載會是Node1和Node3的兩倍。

爲解決一致性hash算法帶來的負載不均衡問題,需要使用虛擬節點的思想:可通過將每臺物理服務器虛擬成一組虛擬緩存服務器,將虛擬服務器的hash值放置在hash環上,KEY在環上先找到虛擬服務器節點,然後再映射到實際的服務器上。

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

虛擬節點的hash計算可以採用對應節點的 IP 地址加數字後綴的方式。例如假設 serverA 的 IP 地址爲 127.0.0.1 。引入虛擬節點前,計算serverA 的 hash 值:

hash(“127.0.0.1”);

引入虛擬節點後,計算虛擬節點serverA1 和 serverA12 的 hash 值:hash(“127.0.0.1#1”);  

hash(“127.0.0.1#2”);

 

節點變化數據分流的問題

上面討論的節點變化都會導致部分緩存數據的重新分佈,hash算法還有一個重要的衡量指標:hash算法的結果能夠保證需要重新分佈的緩存數據能映射到新的server節點中。

 

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

取模算法的方法簡單,數據的分散性也可以,但其主要缺點是當添加或移除server節點時,緩存重新映射的代價相當巨大。添加或移除server節點時,餘數就會產生鉅變,這樣就無法定位與存儲時相同的server節點,從而影響緩存的命中率。而一致性hash算法則最大限度的減少了server節點變化帶來的影響,當節點變化時,隻影響一個server節點的部分數據,且hash算法能夠保證需要重新分佈的緩存數據能映射到新的server節點中。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章