Hash環
我們把232次方想成一個環,比如鐘錶上有60個分針點組成一個圓,那麼hash環就是由232個點組成的圓。第一個點是0,最後一個點是232-1,我們把這232個點組成的環稱之爲HASH環。
![圖片](https://uploader.shimo.im/f/FcmwzbmsdosBR1Q4.png!thumbnail)
一致性Hash算法
將memcached物理機節點通過Hash算法虛擬到一個虛擬閉環上(由0到232構成),key請求的時候通過Hash算法計算出Hash值然後對232取模,定位到環上順時針方向最接近的虛擬物理節點就是要找到的緩存服務器。
假設有ABC三臺緩存服務器:
我們使用這三臺服務器各自的IP進行hash計算然後對2~32取模即:
***Hash(服務器IP)%2~32***
計算出來的結果是0到2~32-1的一個整數,那麼Hash環上必有一個點與之對應。比如:
現在緩存服務器已經落到了Hash環上,接下來我們就看我們的數據是怎麼放到緩存服務器的?
我們可以同樣對Object取Hash值然後對2~32取模,比如落到了接近A的一個點上:
那麼這個數據理應存到A這個緩存服務器節點上
所以,在緩存服務器節點數量不變的情況下,緩存的落點是不會變的。
但是如果B掛掉了呢?
按照hash且取模的算法,圖中3這個Object理應就分配到了C這個節點上去了,所以就會到C上找緩存數據,結果當然是找不到,進而從DB讀取數據重新放到了C上。
但是對於編號爲1,2的Object還是落到A,編號爲4的Object還是落到C,B宕機所影響的僅僅是3這個Object。這就是一致性Hash算法的優點。
Hash環的傾斜
前面我們理想化的把三臺memcache機器均勻分到了Hash環上:
但是現實情況可能是:
如果Hash環傾斜,即緩存服務器過於集中將會導致大量緩存數據被分配到了同一個服務器上。比如編號1,2,3,4,6的Object都被存到了A,5被存到B,而C上竟然一個數據都沒有,這將造成內存空間的浪費。
爲了解決這個問題,一致性Hash算法中使用“虛擬節點”解決。
虛擬節點解決Hash環傾斜
“虛擬節點”是“實際節點”在hash環上的複製品,一個實際節點可能對應多個虛擬節點。這樣就可以將ABC三臺服務器相對均勻分配到Hash環上,以減少Hash環傾斜的影響,使得緩存被均勻分配到hash環上。
Hash算法平衡性
平衡性指的是hash的結果儘可能分佈到所有的緩存中去,這樣可以使得所有的緩存空間都可以得到利用。但是hash算法不保證絕對的平衡性,爲了解決這個問題一致性hash引入了“虛擬節點”的概念。虛擬節點”( virtual node )是實際節點在 hash 空間的複製品( replica ),一實際個節點對應了若干個“虛擬節點”,這個對應個數也成爲“複製個數”,“虛擬節點”在 hash 空間中以 hash 值排列。“虛擬節點”的hash計算可以採用對應節點的IP地址加數字後綴的方式。
例如假設 cache A 的 IP 地址爲202.168.14.241 。
引入“虛擬節點”前,計算 cache A 的 hash 值:
Hash(“202.168.14.241”);
引入“虛擬節點”後,計算“虛擬節”點 cache A1 和 cache A2 的 hash 值:
Hash(“202.168.14.241#1”); // cache A1
Hash(“202.168.14.241#2”); // cache A2
這樣只要是命中cacheA1和cacheA2節點,就相當於命中了cacheA的緩存。這樣平衡性就得到了提高。