一致 Hash 算法
當我們在做數據庫分庫分表或者是分布式緩存時,不可避免的都會遇到一個問題:
如何將數據均勻的分散到各個節點中,并且盡量的在加減節點時能使受影響的數據最少。
Hash 取模
隨機放置就不說了,會帶來很多問題。通常最容易想到的方案就是?hash 取模了。
可以將傳入的 Key 按照?index = hash(key) % N?這樣來計算出需要存放的節點。其中 hash 函數是一個將字符串轉換為正整數的哈希映射方法,N 就是節點的數量。
這樣可以滿足數據的均勻分配,但是這個算法的容錯性和擴展性都較差。
比如增加或刪除了一個節點時,所有的 Key 都需要重新計算,顯然這樣成本較高,為此需要一個算法滿足分布均勻同時也要有良好的容錯性和拓展性。
一致 Hash 算法
一致 Hash 算法是將所有的哈希值構成了一個環,其范圍在?0 ~ 2^32-1。如下圖:
之后將各個節點散列到這個環上,可以用節點的 IP、hostname 這樣的唯一性字段作為 Key 進行?hash(key),散列之后如下:
之后需要將數據定位到對應的節點上,使用同樣的?hash 函數?將 Key 也映射到這個環上。
這樣按照順時針方向就可以把 k1 定位到?N1節點,k2 定位到?N3節點,k3 定位到?N2節點。
容錯性
這時假設 N1 宕機了:
依然根據順時針方向,k2 和 k3 保持不變,只有 k1 被重新映射到了 N3。這樣就很好的保證了容錯性,當一個節點宕機時只會影響到少少部分的數據。
拓展性
當新增一個節點時:
在 N2 和 N3 之間新增了一個節點 N4 ,這時會發現受印象的數據只有 k3,其余數據也是保持不變,所以這樣也很好的保證了拓展性。
虛擬節點
到目前為止該算法依然也有點問題:
當節點較少時會出現數據分布不均勻的情況:
這樣會導致大部分數據都在 N1 節點,只有少量的數據在 N2 節點。
為了解決這個問題,一致哈希算法引入了虛擬節點。將每一個節點都進行多次 hash,生成多個節點放置在環上稱為虛擬節點:
計算時可以在 IP 后加上編號來生成哈希值。
這樣只需要在原有的基礎上多一步由虛擬節點映射到實際節點的步驟即可讓少量節點也能滿足均勻性。
總結
以上是生活随笔為你收集整理的一致 Hash 算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何成为一位「不那么差」的程序员
- 下一篇: Fluentd初探 简介与安装