工程師常使用服務器集群來設計和實現數據緩存,以下是常見的策略:
1.無論是添加、查詢還是刪除數據,都先將數據的id通過哈希函數轉換成一個哈希值,記為key。
2.如果目前機器有N 台,則計算key%N的值,這個值就是該數據所屬的機器編號,無論是添加、刪除還是查詢操作,都只在這台機器上進行。
請分析這種緩存策略可能帶來的問題,並提出改進的方案。
普通Hash算法

緩存策略的潛在問題是如果增加或刪除機器時(N變化)代價會很高,所有的數據都不得不根據id重新計算一遍哈希值,並將哈希值對新的機器數進行取模操作,然后進行大規模的數據遷移為了解決這些問題,引入一致性哈希算法。假設數據的id通過哈希函數轉換成的哈希值范圍是2^32,也就是(0~2^32-1)的數字空間中。
我們將這些數字頭尾相連,想象成一個閉合的環形,那么一個數字id在計算出哈希值之后認為對應到環中的一個位置上接下來,想象有三台機器也處於這樣一個環中,這三台機器在環中的位置根據機器id計算出的哈希值來決定。那么一條數據如何確定歸屬哪台機器呢?首先把該數據的id用哈希值算出哈希值,並映射到環中的相應位置,然后順時針找尋離這個位置最近的機器,那台機器就是該數據的歸屬。例如,下圖有一個數據m,計算其hash值后映射到環上,那么他的歸屬就是2號機器

普通hash求余算法最為不妥的地方就是在有機器的添加或者刪除之后會照成大量的對象存儲位置失效,這樣就大大的不滿足單調性了。下面來分析一下一致性哈希算法是如何處理的
一致性哈希算法
1.結點(機器)刪除
以上面的分布為例,如果Node2(機器2)出現故障被刪除了,那么按照順時針遷移的方法,Hash值屬於圖中紅色片段的所有數據將會被遷移到Node3(機器)中,這樣僅僅是紅色的一段映射位置發生了變化,其它的對象沒有任何的改動。如下圖:

2.結點(機器)添加
如果往集群中添加一個新的節點NODE4,通過對應的哈希算法得到KEY4,並映射到環中,如下圖:

按照順時針遷移的規則,數據Hash值處於紅色段的數據被遷移到了Node4中,其它對象還保持這原有的存儲位置。通過對節點的添加和刪除的分析,一致性哈希算法在保持了單調性的同時,數據的遷移時間達到了最小,這樣的算法對分布式集群來說是非常合適的,避免了大量數據遷移,減小了服務器的的壓力
一致性哈希算法優化
其實上面的一致性哈希函數還存在一個很大的問題,我們說Hash函數是輸入的樣本量很大的時候,其輸出結果在輸出域上是均勻分布的,但是這里假如只有三個輸入,就很難保證分布是均勻的,有可能產生下圖所示的分布,就導致負載極其不均衡

更加優化的一致性哈希算法引入了虛擬節點機制,即對每一台機器產生多個結點,稱為虛擬節點。具體做法可以在機器ip或主機名的后面增加編號或端口號來實現。假設一台機器有1000個虛擬節點,3台機器就有3000個結點,3000個結點映射到哈希域上就相對比較均勻了
