平衡性是指哈希的結果可以儘量分佈在全部的緩衝(Cache)中去,這樣可使得全部的緩衝空間獲得利用。不少哈希算法都可以知足這一條件。程序員
單調性是指若是已經有一些內容經過哈希分派到了相應的緩衝中,又有新的緩衝加入到系統中。哈希的結果應該可以保證原有已分配的內容能夠被映射到原有的或者新的緩衝中去,而不會映射到舊的緩衝集合中的其餘緩衝區。算法
在分佈式環境中,終端有可能看不到全部的緩衝,而只能看到其中的一部分。當終端但願經過哈希過程將內容映射到緩衝上去,因爲不一樣終端所見的緩衝範圍有可能不一樣,從而致使哈希的結果不一致,最終的結果是相同的內容被不一樣的終端映射到不一樣的緩衝區中。這種狀況顯然是應該避免的,由於它致使相同內容被存儲到不一樣緩衝中去,下降了系統存儲的效率。分散性的定義就是上述狀況發生的嚴重程度。好的哈希算法應該可以儘可能避免不一致的狀況發生,也就是儘可能下降分散性。segmentfault
負載問題其實是從另外一個角度看待分散性問題。既然不一樣的終端可能將相同的內容映射到不一樣的緩衝區中,那麼對於一個特定的緩衝區而言,也可能被不一樣的用戶映射到不一樣的內容。與分散性同樣,這種狀況也是應當避免的,所以好的哈希算法應可以儘可能下降緩衝的負荷。服務器
一、簡單來講,一致性哈希將整個哈希值空間組織成一個虛擬的圓環,如假設某哈希函數H的值空間爲0-2^32-1(即哈希值是一個32位無符號整形),整個哈希空間環以下:
二、整個空間按順時針方向組織。0到2的32次方減1微信
2^{32} -1
在零點中方向重合。下一步將各個服務器使用Hash進行一個哈希,具體能夠選擇服務器的ip或主機名做爲關鍵字進行哈希,這樣每臺機器就能肯定其在哈希環上的位置,這裏假設將上文中四臺服務器使用ip地址哈希後在環空間的位置以下:
三、接下來使用以下算法定位數據訪問到相應服務器:將數據key使用相同的函數Hash計算出哈希值,並肯定此數據在環上的位置,今後位置沿環順時針「行走」,第一臺遇到的服務器就是其應該定位到的服務器。
例如咱們有NODE一、NODE二、NODE三、NODE4四個數據對象,通過哈希計算後,在環空間上的位置以下:
分佈式
四、根據一致性哈希算法,數據A會被定爲到Node 1上,數據B被定爲到Node 2上,數據C被定爲到Node 3上,數據D被定爲到Node 4上。
下面分析一致性哈希算法的容錯性和可擴展性。現假設Node 3不幸宕機,能夠看到此時數據A、B、D不會受到影響,只有數據C被重定位到Node 4。通常的,在一致性哈希算法中,若是一臺服務器不可用,則受影響的數據僅僅是此服務器到其環空間中前一臺服務器(即沿着逆時針方向行走遇到的第一臺服務器)之間數據,其它不會受到影響。
下面考慮另一種狀況,若是在系統中增長一臺服務器Node X,以下圖所示:
五、此時對象Object A、B、D不受影響,只有對象C須要重定位到新的Node X 。通常的,在一致性哈希算法中,若是增長一臺服務器,則受影響的數據僅僅是新服務器到其環空間中前一臺服務器(即沿着逆時針方向行走遇到的第一臺服務器)之間數據,其它數據也不會受到影響。函數
例如系統中只有兩臺服務器,其環分佈以下,
六、此時必然形成大量數據集中到Node 1上,而只有極少許會定位到Node 2上以下圖:
爲了解決這種數據傾斜問題,一致性哈希算法引入了虛擬節點機制,即對每個服務節點計算多個哈希,每一個計算結果位置都放置一個此服務節點,稱爲虛擬節點。具體作法能夠在服務器ip或主機名的後面增長編號來實現。
例如上面的狀況,能夠爲每臺服務器計算三個虛擬節點,因而能夠分別計算 「Node 1」、「Node 1#」、「Node 1#」、「Node 2」、「Node 2#」、「Node2#」的哈希值,因而造成六個虛擬節點:
七、同時數據定位算法不變,只是多了一步虛擬節點到實際節點的映射,例如定位到「Node 1#」、「Node 1」、「Node 1#」三個虛擬節點的數據均定位到Node 1上。這樣就解決了服務節點少時數據傾斜的問題。在實際應用中,一般將虛擬節點數設置爲32甚至更大,所以即便不多的服務節點也能作到相對均勻的數據分佈。
幫忙關注一下 微信公衆號一塊兒學習 :chengxuyuan95(不同的程序員)學習