一緻性雜湊演算法在1997年由麻省理工學院提出的一種分布式哈希(DHT)實作算法,設計目标是為了解決網際網路中的熱點(Hot spot)問題,初衷和CARP十分相似。一緻性哈希修正了CARP使用的簡 單雜湊演算法帶來的問題。使得分布式哈希(DHT)能夠在P2P環境中真正得到應用。
一緻性hash算法提出了在動态變化的Cache環境中。判定雜湊演算法好壞的四個定義:
1、平衡性(Balance):平衡性是指哈希的結果能夠盡可能分布到全部的緩沖中去,這樣能夠使得全部的緩沖空間都得到利用。非常多雜湊演算法都能夠滿足這一條件。
2、單調性(Monotonicity):單調性是指假設已經有一些内容通過哈希分派到了相應的緩沖中,又有新的緩沖加入到系統中。哈希的結果應能夠保證原有已配置設定的内容能夠被映射到原有的或者新的緩沖中去,而不會被映射到舊的緩沖集合中的其他緩沖區。
3、分散性(Spread):在分布式環境中。終端有可能看不到全部的緩沖。而是僅僅能看到當中的一部分。當終端希望通過哈希過程将内容映射到緩沖上時,由于不同終端所見的緩沖範圍有可能不同。進而導緻哈希的結果不一緻。終于的結果是同樣的内容被不同的終端映射到不同的緩沖區中。這種情況顯然是應該避免的。由于它導緻同樣内容被存儲到不同緩沖中去,減少了系統存儲的效率。
分散性的定義就是上述情況發生的嚴重程度。
好的雜湊演算法應能夠盡量避免不一緻的情況發生。也就是盡量減少分散性。
4、負載(Load):負載問題實際上是從還有一個角度看待分散性問題。
既然不同的終端可能将同樣的内容映射到不同的緩沖區中。那麼對于一個特定的緩沖區而言,也可能被不同的使用者映射為不同 的内容。與分散性一樣,這種情況也是應當避免的。是以好的雜湊演算法應能夠盡量減少緩沖的負荷。
在分布式叢集中。對機器的加入删除。或者機器故障後自己主動脫離叢集這些操作是分布式叢集管理最主要的功能。假設採用經常使用的hash(object)%N算法,那麼在有機器加入或者删除後。非常多原有的資料就無法找到了,這樣嚴重的違反了單調性原則。接下來主要解說一下一緻性雜湊演算法是怎樣設計的:
環形Hash空間
依照經常使用的hash算法來将相應的key哈希到一個具有2^32次方個桶的空間中,即0~(2^32)-1的數字空間中。如今我們能夠将這些數字頭尾相連,想象成一個閉合的環形。例如以下圖

把資料通過一定的hash算法處理後映射到環上
如今我們将object1、object2、object3、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中,object2、object4存儲到了NODE3中。在這種部署環境中,hash環是不會變更的,是以。通過算出對象的hash值就能高速的定位到相應的機器中。這樣就能找到對象真正的存儲位置了。
機器的删除與加入
普通hash求餘算法最為不妥的地方就是在有機器的加入或者删除之後會照成大量的對象存儲位置失效,這樣就大大的不滿足單調性了。以下來分析一下一緻性雜湊演算法是怎樣處理的。
1. 節點(機器)的删除
以上面的分布為例,假設NODE2出現問題被删除了。那麼依照順時針遷移的方法。object3将會被遷移到NODE3中,這樣僅僅是object3的映射位置發生了變化,其他的對象沒有不論什麼的修改。例如以下圖:
2. 節點(機器)的加入
假設往叢集中加入一個新的節點NODE4,通過相應的雜湊演算法得到KEY4,并映射到環中。例如以下圖:
通過按順時針遷移的規則。那麼object2被遷移到了NODE4中,其他對象還保持這原有的存儲位置。通過對節點的加入和删除的分析。一緻性雜湊演算法在保持了單調性的同一時候。還是資料的遷移達到了最小,這種算法對分布式叢集來說是非常合适的,避免了大量資料遷移,減小了server的的壓力。
平衡性
依據上面的圖解分析,一緻性雜湊演算法滿足了單調性和負載均衡的特性以及一般hash算法的分散性。但這還并不能當做其被廣泛應用的原由。由于還缺少了平衡性。以下将分析一緻性雜湊演算法是怎樣滿足平衡性的。
hash算法是不保證平衡的。如上面僅僅部署了NODE1和NODE3的情況(NODE2被删除的圖),object1存儲到了NODE1中。而object2、object3、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