說出來你們可能不相信,我昨天作夢夢到本身在面試,而後面試官問了我這個問題哈哈~而後我就打算按照本身的理解寫一寫。若是有寫的不對的歡迎你們指正!node
普通hash算法就是把存儲的key取hash而後再對節點數取模以後判斷key所在節點的位置,面試
如上圖所示,假設如今有key1,key2,key3,key4四個key,經過上面說的方法均勻分佈在了這4個節點上面。看上去很是nice~算法
可是若是如今咱們集羣須要擴容,增長一臺機器會發生啥?緩存
能夠看到,因爲如今增長了一臺機器,因此如今咱們取模的對象由3變成了4。優化
致使什麼現象呢?假設咱們的數據如今沒有遷移,那原來的key3和key4原本是分別在node0和node1上的,如今經過hash取模運算以後倒是在node0和node3上,因此在數據不作遷移的狀況下會致使原有的緩存會大量失效。而後這種大面積的數據遷移是很是麻煩的!3d
這是擴容致使的問題,若是集羣中的節點宕機呢?對象
如今node2掛了,集羣節點數量變成了2,對應的key經過hash取模以後所在的節點也會變化。致使node2上面原有的key查詢不到,會直接查庫。其他的key,除了key1能正常查詢外,其餘key全都失效了。這時不只涉及到數據遷移還會致使緩存穿透。blog
一致性hash實際上是普通取模hash算法的改良版,其hash計算方法沒有變化,可是hash空間發生了變化,由原來的線性的變成了環。緩存節點經過hash計算以後獲得在hash環中的位置;key經過hash計算以後獲得所在環的位置,而後順時針方向找到第一個節點,這個節點就是存放key的節點。hash
來看看一致性hash是如何解決普通取模hash中擴容和宕機的問題的。集羣
假設如今咱們增長了一個節點node3,原來的key1如今順時針找到了新增長node3,對其他的節點沒有任何影響。只須要將node0到node3之間的key遷移到新的節點便可。
若是node2如今宕機了,那麼原來的key2順時針找到的節點會變成node0,其他節點也沒有任何影響,只須要把node2上的key遷移到node0上便可。
那這個一致性hash難道就沒有啥毛病了嘛?
想一下,若是咱們的節點數量不多,而且節點偏向一側會發生什麼事情?
能夠看到很大一部分的key都會落在node0上,從而致使node0的壓力過大掛掉,node0掛掉以後數據同時又會向node1上轉移,node1又會掛掉,最終致使整個集羣不可用!這就是數據傾斜的問題,會引發節點雪崩。可想而知這個問題會很嚴重。
數據傾斜的問題是經過虛擬節點來解決的。
就是在節點稀疏的hash環上對物理節點虛擬出一部分虛擬節點,key會打到虛擬節點上面,而虛擬節點上的key實際也是映射到物理節點上的,這樣就避免了數據傾斜致使單節點壓力過大致使節點雪崩的問題。
作夢引發的一片博文。
介紹了普通取模hash的弊端,一致性hash如何解決,以及一致性hash優化的問題。
上面的介紹若是有什麼不對的地方但願各位能指正~我也會虛心接受。