哈希算法原理和一致性哈希算法

簡單哈希算法

一.概念

 

哈希表就是一種以 鍵-值(key-indexed) 存儲數據的結構,咱們只要輸入待查找的值即key,便可查找到其對應的值。node

哈希的思路很簡單,若是全部的鍵都是整數,那麼就可使用一個簡單的無序數組來實現:將鍵做爲索引,值即爲其對應的值,這樣就能夠快速訪問任意鍵的值。這是對於簡單的鍵的狀況,咱們將其擴展到能夠處理更加複雜的類型的鍵。算法

使用哈希查找有兩個步驟:數組

1. 使用哈希函數將被查找的鍵轉換爲數組的索引。在理想的狀況下,不一樣的鍵會被轉換爲不一樣的索引值,可是在有些狀況下咱們須要處理多個鍵被哈希到同一個索引值的狀況。因此哈希查找的第二個步驟就是處理衝突服務器

2. 處理哈希碰撞衝突。有不少處理哈希碰撞衝突的方法,本文後面會介紹拉鍊法和線性探測法。負載均衡

哈希表是一個在時間和空間上作出權衡的經典例子。若是沒有內存限制,那麼能夠直接將鍵做爲數組的索引。那麼全部的查找時間複雜度爲O(1);若是沒有時間限制,那麼咱們可使用無序數組並進行順序查找,這樣只須要不多的內存。哈希表使用了適度的時間和空間來在這兩個極端之間找到了平衡。只須要調整哈希函數算法便可在時間和空間上作出取捨。dom

 

 

在Hash表中,記錄在表中的位置和其關鍵字之間存在着一種肯定的關係。這樣咱們就能預先知道所查關鍵字在表中的位置,從而直接經過下標找到記錄。使ASL趨近與0.分佈式

 

              1)   哈希(Hash)函數是一個映象,即: 將關鍵字的集合映射到某個地址集合上,它的設置很靈活,只要這個地       址集合的大小不超出容許範圍便可;函數

             2)  因爲哈希函數是一個壓縮映象,所以,在通常狀況下,很容易產生「衝突」現象,即: key1!=key2,而  f  (key1) = f(key2)。性能

              3).  只能儘可能減小衝突而不能徹底避免衝突,這是由於一般關鍵字集合比較大,其元素包括全部可能的關鍵字, 而地址集合的元素僅爲哈希表中的地址值測試

 

       在構造這種特殊的「查找表」 時,除了須要選擇一個「好」(儘量少產生衝突)的哈希函數以外;還須要找到一 種「處理衝突」 的方法。

 

二.Hash構造函數的方法

 

   1.直接定址法:

                         

 直接定址法是以數據元素關鍵字k自己或它的線性函數做爲它的哈希地址,即:H(k)=k  或 H(k)=a×k+b ; (其中a,b爲常數)

  例1,有一我的口統計表,記錄了從1歲到100歲的人口數目,其中年齡做爲關鍵字,哈希函數取關鍵字自己,如圖(1):

地址

A1

A2

……

A99

A100

年齡

1

2

……

99

100

人數

980

800

……

495

107

能夠看到,當須要查找某一年齡的人數時,直接查找相應的項便可。如查找99歲的老人數,則直接讀出第99項便可。

 

地址

A0

A1

……

A99

A100

年齡

1980

1981

……

1999

2000

人數

980

800

……

495

107

 

若是咱們要統計的是80後出生的人口數,如上表所示,那麼咱們隊出生年份這個關鍵字能夠用年份減去1980來做爲地址,此時f(key)=key-1980

這種哈希函數簡單,而且對於不一樣的關鍵字不會產生衝突,但能夠看出這是一種較爲特殊的哈希函數,實際生活中,關鍵字的元素不多是連續的。用該方法產生的哈希表會形成空間大量的浪費,所以這種方法適應性並不強。[2]

  此法僅適合於:地址集合的大小 = = 關鍵字集合的大小,其中a和b爲常數。

 

 

2.數字分析法:

             假設關鍵字集合中的每一個關鍵字都是由 s 位數字組成 (u1, u2, …, us),分析關鍵字集中的全體,並從中提取分佈均勻的若干位或它們的組合做爲地址。

數字分析法是取數據元素關鍵字中某些取值較均勻的數字位做爲哈希地址的方法。即當關鍵字的位數不少時,能夠經過對關鍵字的各位進行分析,丟掉分佈不均勻的位,做爲哈希值。它只適合於全部關鍵字值已知的狀況。經過分析分佈狀況把關鍵字取值區間轉化爲一個較小的關鍵字取值區間。

   例2,要構造一個數據元素個數n=80,哈希長度m=100的哈希表。不失通常性,咱們這裏只給出其中8個關鍵字進行分析,8個關鍵字以下所示:

K1=61317602      K2=61326875      K3=62739628      K4=61343634

K5=62706815      K6=62774638      K7=61381262      K8=61394220

分析上述8個關鍵字可知,關鍵字從左到右的第一、二、三、6位取值比較集中,不宜做爲哈希地址,剩餘的第四、五、七、8位取值較均勻,可選取其中的兩位做爲哈希地址。設選取最後兩位做爲哈希地址,則這8個關鍵字的哈希地址分別爲:2,75,28,34,15,38,62,20。           

 

 此法適於:能預先估計出全體關鍵字的每一位上各類數字出現的頻度。

             

3.摺疊法:

            將關鍵字分割成若干部分,而後取它們的疊加和爲哈希地址。兩種疊加處理的方法:移位疊加:將分 割後的幾部分低位對齊相加;邊界疊加:從一端沿分割界來回摺疊,而後對齊相加。

所謂摺疊法是將關鍵字分割成位數相同的幾部分(最後一部分的位數能夠不一樣),而後取這幾部分的疊加和(捨去進位),這方法稱爲摺疊法。這種方法適用於關鍵字位數較多,並且關鍵字中每一位上數字分佈大體均勻的狀況。

  摺疊法中數位摺疊又分爲移位疊加和邊界疊加兩種方法,移位疊加是將分割後是每一部分的最低位對齊,而後相加;邊界疊加是從一端向另外一端沿分割界來回摺疊,而後對齊相加。

例4,當哈希表長爲1000時,關鍵字key=110108331119891,容許的地址空間爲三位十進制數,則這兩種疊加狀況如圖:

       移位疊加                                 邊界疊加

       8 9 1                                     8 9 1

       1 1 9                                     9 1 1

       3 3 1                                     3 3 1

       1 0 8                                     8 0 1

    +  1 1 0                                   + 1 1 0              

   (1) 5 5 9                                  (3)0 4 4

                 圖(2)由摺疊法求哈希地址

     用移位疊加獲得的哈希地址是559,而用邊界疊加所獲得的哈希地址是44。若是關鍵字不是數值而是字符串,則可先轉化爲數。轉化的辦法能夠用ASCⅡ字符或字符的次序值。

            此法適於:關鍵字的數字位數特別多。

 

4.平方取中法

  這是一種經常使用的哈希函數構造方法。這個方法是先取關鍵字的平方,而後根據可以使用空間的大小,選取平方數是中間幾位爲哈希地址。

哈希函數 H(key)=「key2的中間幾位」由於這種方法的原理是經過取平方擴大差異,平方值的中間幾位和這個數的每一位都相關,則對不一樣的關鍵字獲得的哈希函數值不易產生衝突,由此產生的哈希地址也較爲均勻。

例5,若設哈希表長爲1000則可取關鍵字平方值的中間三位,如圖所示:

關鍵字

關鍵字的平方

哈希函數值

1234

1522756

227

2143

4592449

924

4132

17073424

734

3214

10329796

297 

  

下面給出平方取中法的哈希函數

     //平方取中法哈希函數,結設關鍵字值32位的整數

     //哈希函數將返回key * key的中間10位

       Int  Hash (int key)

         {

     //計算key的平方

      Key * = key ;

     //去掉低11位

     Key>>=11;

     // 返回低10位(即key * key的中間10位)

       Return key %1024;

          }

   此法適於:關鍵字中的每一位都有某些數字重複出現頻度很高的現象

 

 

5.減去法

 

減去法是數據的鍵值減去一個特定的數值以求得數據存儲的位置。

例7,公司有一百個員工,而員工的編號介於1001到1100,減去法就是員工編號減去1000後即爲數據的位置。編號1001員工的數據在數據中的第一筆。編號1002員工的數據在數據中的第二筆…依次類推。從而得到有關員工的全部信息,由於編號1000之前並無數據,全部員工編號都從1001開始編號。

 

 

6.基數轉換法

  將十進制數X看做其餘進制,好比十三進制,再按照十三進制數轉換成十進制數,提取其中若干爲做爲X的哈希值。通常取大於原來基數的數做爲轉換的基數,而且兩個基數應該是互素的。

 

例Hash(80127429)=(80127429)13=8*137+0*136+1*135+2*134+7*133+4*132+2*131+9=(502432641)10若是取中間三位做爲哈希值,得Hash(80127429)=432

 爲了得到良好的哈希函數,能夠將幾種方法聯合起來使用,好比先變基,再摺疊或平方取中等等,只要散列均勻,就能夠隨意拼湊。

 

 

 

  7.除留餘數法:

            

假設哈希表長爲m,p爲小於等於m的最大素數,則哈希函數爲

h(k)=k  %  p ,其中%爲模p取餘運算。

例如,已知待散列元素爲(18,75,60,43,54,90,46),表長m=10,p=7,則有

    h(18)=18 % 7=4    h(75)=75 % 7=5    h(60)=60 % 7=4   

    h(43)=43 % 7=1    h(54)=54 % 7=5    h(90)=90 % 7=6   

    h(46)=46 % 7=4

此時衝突較多。爲減小衝突,可取較大的m值和p值,如m=p=13,結果以下:

    h(18)=18 % 13=5    h(75)=75 % 13=10    h(60)=60 % 13=8    

    h(43)=43 % 13=4    h(54)=54 % 13=2    h(90)=90 % 13=12   

    h(46)=46 % 13=7

此時沒有衝突,如圖8.25所示。

 

0      1      2     3     4     5      6     7     8     9     10     11    12

 

 

 

54

 

43

18

 

46

60

 

75

 

90

                      

 

除留餘數法求哈希地址

 

 

理論研究代表,除留餘數法的模p取不大於表長且最接近表長m素數時效果最好,且p最好取1.1n~1.7n之間的一個素數(n爲存在的數據元素個數)

 

 

8.隨機數法:

           設定哈希函數爲:H(key) = Random(key)其中,Random 爲僞隨機函數

           此法適於:對長度不等的關鍵字構造哈希函數。

 

         實際造表時,採用何種構造哈希函數的方法取決於建表的關鍵字集合的狀況(包括關鍵字的範圍和形態),以及哈希表    長度(哈希地址範圍),總的原則是使產生衝突的可能性降到儘量地小。

 

9.隨機乘數法

  亦稱爲「乘餘取整法」。隨機乘數法使用一個隨機實數f,0≤f<1,乘積f*k的分數部分在0~1之間,用這個分數部分的值與n(哈希表的長度)相乘,乘積的整數部分就是對應的哈希值,顯然這個哈希值落在0~n-1之間。其表達公式爲:Hash(k)=「n*(f*k%1)」其中「f*k%1」表示f*k 的小數部分,即f*k%1=f*k-「f*k」

  例10,對下列關鍵字值集合採用隨機乘數法計算哈希值,隨機數f=0.103149002 哈希表長度n=100得圖:

 

k

f*k

n*((f*k)的小數部分)

Hash(k)

319426

32948.47311

47.78411

47

718309

74092.85648

86.50448

86

629443

64926.41727

42.14427

42

919697

84865.82769

83.59669

83

  此方法的優勢是對n的選擇不很關鍵。一般若地址空間爲p位就是選n=2p.Knuth對常數f的取法作了仔細的研究,他認爲f取任何值均可以,但某些值效果更好。如f=(-1)/2=0.6180329...比較理想。

 

10.字符串數值哈希法

在很都狀況下關鍵字是字符串,所以這樣對字符串設計Hash函數是一個須要討論的問題。下列函數是取字符串前10個字符來設計的哈希函數

Int Hash _ char (char *X)

{

  int I ,sum

  i=0;

  while (i 10 && X[i])

  Sum +=X[i++];

  sum%=N;      //N是記錄的條數

  }

這種函數把字符串的前10個字符的ASCⅡ值之和對N取摸做爲Hash地址,只要N較小,Hash地址將較均勻分佈[0,N]區間內,所以這個函數仍是可用的。對於N很大的情形,可以使用下列函數

int ELFhash (char *key )

{

 Unsigned long h=0,g;

whie (*key)

{

h=(h<<4)+ *key;

key++;

g=h & 0 xF0000000L;

if (g) h^=g>>24;

h & =~g;

}

h=h % N

return (h);

}

  這個函數稱爲ELFHash(Exextable and Linking Format ,ELF,可執行連接格式)函數。它把一個字符串的絕對長度做爲輸入,並經過一種方式把字符的十進制值結合起來,對長字符串和短字符串都有效,這種方式產生的位置不可能不均勻分佈。

 

11.旋轉法

  旋轉法是將數據的鍵值中進行旋轉。旋轉法一般並不直接使用在哈希函數上,而是搭配其餘哈希函數使用。

  例11,某學校同一個系的新生(小於100人)的學號前5位數是相同的,只有最後2位數不一樣,咱們將最後一位數,旋轉放置到第一位,其他的往右移。

新生學號

旋轉過程

旋轉後的新鍵值

5062101

5062101

1506210

5062102

5062102

2506210

5062103

5062103

3506210

5062104

5062104

4506210

5062105

5062105

5506210

                    如圖

 運用這種方法能夠只輸入一個數值從而快速地查到有關學生的信息。

 

 

在實際應用中,應根據具體狀況,靈活採用不一樣的方法,並用實際數據測試它的性能,以便作出正確斷定。一般應考慮如下五個因素 :

l 計算哈希函數所需時間 (簡單)。

l 關鍵字的長度。

l 哈希表大小。

l 關鍵字分佈狀況。

l 記錄查找頻率

 

 

 

三.Hash處理衝突方法

 

   經過構造性能良好的哈希函數,能夠減小衝突,但通常不可能徹底避免衝突,所以解決衝突是哈希法的另外一個關鍵問題。建立哈希表和查找哈希表都會遇到衝突,兩種狀況下解決衝突的方法應該一致。下面以建立哈希表爲例,說明解決衝突的方法。經常使用的解決衝突方法有如下四種:

 經過構造性能良好的哈希函數,能夠減小衝突,但通常不可能徹底避免衝突,所以解決衝突是哈希法的另外一個關鍵問題。建立哈希表和查找哈希表都會遇到衝突,兩種狀況下解決衝突的方法應該一致。下面以建立哈希表爲例,說明解決衝突的方法。經常使用的解決衝突方法有如下四種:

1.         開放定址法

這種方法也稱再散列法,其基本思想是:當關鍵字key的哈希地址p=H(key)出現衝突時,以p爲基礎,產生另外一個哈希地址p1,若是p1仍然衝突,再以p爲基礎,產生另外一個哈希地址p2,…,直到找出一個不衝突的哈希地址pi ,將相應元素存入其中。這種方法有一個通用的再散列函數形式:

          Hi=(H(key)+di% m   i=1,2,…,n

    其中H(key)爲哈希函數,m 爲表長,di稱爲增量序列。增量序列的取值方式不一樣,相應的再散列方式也不一樣。主要有如下三種:

l         線性探測再散列

    dii=1,2,3,…,m-1

這種方法的特色是:衝突發生時,順序查看錶中下一單元,直到找出一個空單元或查遍全表。

l         二次探測再散列

    di=12-1222-22…,k2-k2    ( k<=m/2 )

    這種方法的特色是:衝突發生時,在表的左右進行跳躍式探測,比較靈活。

l         僞隨機探測再散列

    di=僞隨機數序列。

具體實現時,應創建一個僞隨機數發生器,(如i=(i+p) % m),並給定一個隨機數作起點。

例如,已知哈希表長度m=11,哈希函數爲:H(key)= key  %  11,則H(47)=3,H(26)=4,H(60)=5,假設下一個關鍵字爲69,則H(69)=3,與47衝突。若是用線性探測再散列處理衝突,下一個哈希地址爲H1=(3 + 1)% 11 = 4,仍然衝突,再找下一個哈希地址爲H2=(3 + 2)% 11 = 5,仍是衝突,繼續找下一個哈希地址爲H3=(3 + 3)% 11 = 6,此時再也不衝突,將69填入5號單元,參圖8.26 (a)。若是用二次探測再散列處理衝突,下一個哈希地址爲H1=(3 + 12% 11 = 4,仍然衝突,再找下一個哈希地址爲H2=(3 - 12% 11 = 2,此時再也不衝突,將69填入2號單元,參圖8.26 (b)。若是用僞隨機探測再散列處理衝突,且僞隨機數序列爲:2,5,9,……..,則下一個哈希地址爲H1=(3 + 2)% 11 = 5,仍然衝突,再找下一個哈希地址爲H2=(3 + 5)% 11 = 8,此時再也不衝突,將69填入8號單元,參圖8.26 (c)。

 

 

0        1       2      3      4      5       6      7      8       9      10    

 

 

 

 

47

26

60

69

 

 

 

 

         (a) 用線性探測再散列處理衝突

 

 

0        1       2      3      4      5       6      7      8       9      10    

 

 

 

69

47

26

60

 

 

 

 

 

         (b) 用二次探測再散列處理衝突

 

 

0        1       2      3      4      5       6      7      8       9      10    

 

 

 

 

47

26

60

 

 

69

 

 

         (c) 用僞隨機探測再散列處理衝突

 

                      圖8.26開放地址法處理衝突

從上述例子能夠看出,線性探測再散列容易產生「二次彙集」,即在處理同義詞的衝突時又致使非同義詞的衝突。例如,當表中i, i+1 ,i+2三個單元已滿時,下一個哈希地址爲i, 或i+1 ,或i+2,或i+3的元素,都將填入i+3這同一個單元,而這四個元素並不是同義詞。線性探測再散列的優勢是:只要哈希表不滿,就必定能找到一個不衝突的哈希地址,而二次探測再散列和僞隨機探測再散列則不必定。

 

2. 再哈希法

    這種方法是同時構造多個不一樣的哈希函數:

    Hi=RH1key)  i=1,2,…,k

當哈希地址Hi=RH1key)發生衝突時,再計算Hi=RH2key)……,直到衝突再也不產生。這種方法不易產生彙集,但增長了計算時間。

3. 鏈地址法

    這種方法的基本思想是將全部哈希地址爲i的元素構成一個稱爲同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,於是查找、插入和刪除主要在同義詞鏈中進行。鏈地址法適用於常常進行插入和刪除的狀況。

例如,已知一組關鍵字(32,40,36,53,16,46,71,27,42,24,49,64),哈希表長度爲13,哈希函數爲:H(key)= key % 13,則用鏈地址法處理衝突的結果如圖

 



 
  哈希表及處理衝突的方法(轉) - 另外一片天空 - 仰望天空
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

圖鏈地址法處理衝突時的哈希表

本例的平均查找長度 ASL=(1*7+2*4+3*1)=1.5

4.創建公共溢出區

這種方法的基本思想是:將哈希表分爲基本表溢出表兩部分,凡是和基本表發生衝突的元素,一概填入溢出表

 

 一致性哈希算法

 

一致性哈希算法在1997年由麻省理工學院提出的一種分佈式哈希(DHT)實現算法,設計目標是爲了解決因特網中的熱點(Hot spot)問題,初衷和CARP十分相似。一致性哈希修正了CARP使用的簡 單哈希算法帶來的問題,使得分佈式哈希(DHT)能夠在P2P環境中真正獲得應用。 
 
    一致性hash算法提出了在動態變化的Cache環境中,斷定哈希算法好壞的四個定義:
 
一、平衡性(Balance):平衡性是指哈希的結果可以儘量分佈到全部的緩衝中去,這樣可使得全部的緩衝空間都獲得利用。不少哈希算法都可以知足這一條件。
 
二、單調性(Monotonicity):單調性是指若是已經有一些內容經過哈希分派到了相應的緩衝中,又有新的緩衝加入到系統中。哈希的結果應可以保證原有已分配的內容能夠被映射到原有的或者新的緩衝中去,而不會被映射到舊的緩衝集合中的其餘緩衝區。 
 
三、分散性(Spread):在分佈式環境中,終端有可能看不到全部的緩衝,而是隻能看到其中的一部分。當終端但願經過哈希過程將內容映射到緩衝上時,因爲不一樣終端所見的緩衝範圍有可能不一樣,從而致使哈希的結果不一致,最終的結果是相同的內容被不一樣的終端映射到不一樣的緩衝區中。這種狀況顯然是應該避免的,由於它致使相同內容被存儲到不一樣緩衝中去,下降了系統存儲的效率。分散性的定義就是上述狀況發生的嚴重程度。好的哈希算法應可以儘可能避免不一致的狀況發生,也就是儘可能下降分散性。 
 
四、負載(Load):負載問題其實是從另外一個角度看待分散性問題。既然不一樣的終端可能將相同的內容映射到不一樣的緩衝區中,那麼對於一個特定的緩衝區而言,也可能被不一樣的用戶映射爲不一樣 的內容。與分散性同樣,這種狀況也是應當避免的,所以好的哈希算法應可以儘可能下降緩衝的負荷。
 
    在分佈式集羣中,對機器的添加刪除,或者機器故障後自動脫離集羣這些操做是分佈式集羣管理最基本的功能。若是採用經常使用的hash(object)%N算法,那麼在有機器添加或者刪除後,不少原有的數據就沒法找到了,這樣嚴重的違反了單調性原則。接下來主要講解一下一致性哈希算法是如何設計的:
 
環形Hash空間
按照經常使用的hash算法來將對應的key哈希到一個具備2^32次方個桶的空間中,即0~(2^32)-1的數字空間中。如今咱們能夠將這些數字頭尾相連,想象成一個閉合的環形。以下圖
                                                                         
把數據經過必定的hash算法處理後映射到環上
如今咱們將object一、object二、object三、object4四個對象經過特定的Hash函數計算出對應的key值,而後散列到Hash環上。以下圖:
    Hash(object1) = key1;
    Hash(object2) = key2;
    Hash(object3) = key3;
    Hash(object4) = key4;
                                                           
將機器經過hash算法映射到環上
在採用一致性哈希算法的分佈式集羣中將新的機器加入,其原理是經過使用與對象存儲同樣的Hash算法將機器也映射到環中(通常狀況下對機器的hash計算是採用機器的IP或者機器惟一的別名做爲輸入值),而後以順時針的方向計算,將全部對象存儲到離本身最近的機器中。
假設如今有NODE1,NODE2,NODE3三臺機器,經過Hash算法獲得對應的KEY值,映射到環中,其示意圖以下:
Hash(NODE1) = KEY1;
Hash(NODE2) = KEY2;
Hash(NODE3) = KEY3;
                                                             
經過上圖能夠看出對象與機器處於同一哈希空間中,這樣按順時針轉動object1存儲到了NODE1中,object3存儲到了NODE2中,object二、object4存儲到了NODE3中。在這樣的部署環境中,hash環是不會變動的,所以,經過算出對象的hash值就能快速的定位到對應的機器中,這樣就能找到對象真正的存儲位置了。
 
機器的刪除與添加
普通hash求餘算法最爲不妥的地方就是在有機器的添加或者刪除以後會照成大量的對象存儲位置失效,這樣就大大的不知足單調性了。下面來分析一下一致性哈希算法是如何處理的。
1. 節點(機器)的刪除
    以上面的分佈爲例,若是NODE2出現故障被刪除了,那麼按照順時針遷移的方法,object3將會被遷移到NODE3中,這樣僅僅是object3的映射位置發生了變化,其它的對象沒有任何的改動。以下圖:
                                                              
2. 節點(機器)的添加 
    若是往集羣中添加一個新的節點NODE4,經過對應的哈希算法獲得KEY4,並映射到環中,以下圖:
                                                              
    經過按順時針遷移的規則,那麼object2被遷移到了NODE4中,其它對象還保持這原有的存儲位置。經過對節點的添加和刪除的分析,一致性哈希算法在保持了單調性的同時,仍是數據的遷移達到了最小,這樣的算法對分佈式集羣來講是很是合適的,避免了大量數據遷移,減少了服務器的的壓力。
 
平衡性
根據上面的圖解分析,一致性哈希算法知足了單調性和負載均衡的特性以及通常hash算法的分散性,但這還並不能當作其被普遍應用的起因,由於還缺乏了平衡性。下面將分析一致性哈希算法是如何知足平衡性的。hash算法是不保證平衡的,如上面只部署了NODE1和NODE3的狀況(NODE2被刪除的圖),object1存儲到了NODE1中,而object二、object三、object4都存儲到了NODE3中,這樣就照成了很是不平衡的狀態。在一致性哈希算法中,爲了儘量的知足平衡性,其引入了虛擬節點。
    ——「虛擬節點」( virtual node )是實際節點(機器)在 hash 空間的複製品( replica ),一實際個節點(機器)對應了若干個「虛擬節點」,這個對應個數也成爲「複製個數」,「虛擬節點」在 hash 空間中以hash值排列。
以上面只部署了NODE1和NODE3的狀況(NODE2被刪除的圖)爲例,以前的對象在機器上的分佈很不均衡,如今咱們以2個副本(複製個數)爲例,這樣整個hash環中就存在了4個虛擬節點,最後對象映射的關係圖以下:
                                                                 
根據上圖可知對象的映射關係:object1->NODE1-1,object2->NODE1-2,object3->NODE3-2,object4->NODE3-1。經過虛擬節點的引入,對象的分佈就比較均衡了。那麼在實際操做中,正真的對象查詢是如何工做的呢?對象從hash到虛擬節點到實際節點的轉換以下圖:
                                         
「虛擬節點」的hash計算能夠採用對應節點的IP地址加數字後綴的方式。例如假設NODE1的IP地址爲192.168.1.100。引入「虛擬節點」前,計算 cache A 的 hash 值:
Hash(「192.168.1.100」);
引入「虛擬節點」後,計算「虛擬節」點NODE1-1和NODE1-2的hash值:
Hash(「192.168.1.100#1」); // NODE1-1
Hash(「192.168.1.100#2」); // NODE1-2
 
 

參考 http://blog.csdn.net/tanggao1314/article/details/51457585

        http://blog.csdn.net/cywosp/article/details/23397179/

        http://blog.huanghao.me/?p=14

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息