在解決分佈式系統中負載均衡的問題時候可使用Hash算法讓固定的一部分請求落到同一臺服務器上,這樣每臺服務器固定處理一部分請求(並維護這些請求的信息),起到負載均衡的做用。可是普通的餘數hash(hash(好比用戶id)%服務器機器數)算法伸縮性不好,當新增或者下線服務器機器時候,用戶id與服務器的映射關係會大量失效。一致性hash則利用hash環對其進行了改進。算法
爲了能直觀的理解一致性hash原理,這裏結合一個簡單的例子來說解,假設有4臺服務器,地址爲ip1,ip2,ip3,ip4。服務器
一致性hash是首先計算四個ip地址對應的hash值
hash(ip1),hash(ip2),hash(ip3),hash(ip3),計算出來的hash值是0~最大正整數直接的一個值,這四個值在一致性hash環上呈現以下圖:負載均衡
如上圖可知user1,user2的請求會落到服務器ip2進行處理,User3的請求會落到服務器ip3進行處理,user4的請求會落到服務器ip4進行處理,user5,user6的請求會落到服務器ip1進行處理。分佈式
下面考慮當ip2的服務器掛了的時候會出現什麼狀況?當ip2的服務器掛了的時候,一致性hash環大體以下圖:3d
根據順時針規則可知user1,user2的請求會被服務器ip3進行處理,而其它用戶的請求對應的處理服務器不變,也就是隻有以前被ip2處理的一部分用戶的映射關係被破壞了,而且其負責處理的請求被順時針下一個節點委託處理。blog
下面考慮當新增機器的時候會出現什麼狀況?當新增一個ip5的服務器後,一致性hash環大體以下圖:ip
根據順時針規則可知以前user1的請求應該被ip1服務器處理,如今被新增的ip5服務器處理,其餘用戶的請求處理服務器不變,也就是新增的服務器順時針最近的服務器的一部分請求會被新增的服務器所替代。ci
服務器ip1,ip2,ip3通過hash後落到了一致性hash環上,從圖中hash值分佈可知ip1會負責處理大概80%的請求,而ip2和ip3則只會負責處理大概20%的請求,雖然三個機器都在處理請求,可是明顯每一個機器的負載不均衡,這樣稱爲一致性hash的傾斜,虛擬節點的出現就是爲了解決這個問題。路由
當服務器節點比較少的時候會出現上節所說的一致性hash傾斜的問題,一個解決方法是多加機器,可是加機器是有成本的,那麼就加虛擬節點,好比上面三個機器,每一個機器引入1個虛擬節點後的一致性hash環的圖以下:hash
其中ip1-1是ip1的虛擬節點,ip2-1是ip2的虛擬節點,ip3-1是ip3的虛擬節點。可知當物理機器數目爲M,虛擬節點爲N的時候,實際hash環上節點個數爲M*N。好比當客戶端計算的hash值處於ip2和ip3或者處於ip2-1和ip3-1之間時候使用ip3服務器進行處理。
上節咱們使用虛擬節點後的圖看起來比較均衡,可是若是生成虛擬節點的算法不夠好極可能會獲得下面的環:
可知每一個服務節點引入1個虛擬節點後,狀況相比沒有引入前均衡性有所改善,可是並不均衡。均衡的一致性hash應該是以下圖:
均勻一致性hash的目標是若是服務器有N臺,客戶端的hash值有M個,那麼每一個服務器應該處理大概M/N個用戶的。也就是每臺服務器負載儘可能均衡