現在我們假設有100臺redis data伺服器,乙份資料101進來的時候,以雜湊公式hash(i)&100,計算所存放的伺服器,假設hash(i) = i,那麼資料被雜湊到標號為1的伺服器,然後這個時候伺服器新增了一台,然後雜湊公式為hash(i)%101,這個時候請求訪問資料101的時候,被分配至0號伺服器,但是其實這個時候資料是在1號伺服器的。
所以這個時候,我們假設是新增了伺服器,如果是持久化儲存的,我們可以讓伺服器集群對資料進行重新雜湊,進行資料遷移,然後進行恢復,但是這個時候就意味著每次增減伺服器的時候,集群就需要大量的通訊,進行資料遷移,這個開銷是非常大的。如果只是快取,那麼快取就都失效了。所以這個時候怎麼辦?
傳統的取模方式
例如10條資料,3個節點,如果按照取模的方式,那就是
node a: 0,3,6,9
node b: 1,4,7
node c: 2,5,8
當增加乙個節點的時候,資料分布就變更為
node a:0,4,8
node b:1,5,9
node c: 2,6
node d: 3,7
總結:資料3,4,5,6,7,8,9在增加節點的時候,都需要做搬遷,成本太高
一致性雜湊方式
最關鍵的區別就是,對節點和資料,都做一次雜湊運算,然後比較節點和資料的雜湊值,資料取和節點最相近的節點做為存放節點。這樣就保證當節點增加或者減少的時候,影響的資料最少。
還是拿剛剛的例子,(用簡單的字串的ascii碼做雜湊key):
十條資料,算出各自的雜湊值
0:192
1:196
2:200
3:204
4:208
5:212
6:216
7:220
8:224
9:228
有三個節點,算出各自的雜湊值
node a: 203
node g: 209
node z: 228
這個時候比較兩者的雜湊值,如果大於228,就歸到前面的203,相當於整個雜湊值就是乙個環,對應的對映結果:
node a: 0,1,2
node g: 3,4
node z: 5,6,7,8,9
這個時候加入node n, 就可以算出node n的雜湊值:
node n: 216
這個時候對應的資料就會做遷移:
node a: 0,1,2
node g: 3,4
node n: 5,6
node z: 7,8,9
這個時候只有5和6需要做遷移
另外,這個時候如果只算出三個雜湊值,那再跟資料的雜湊值比較的時候,很容易分得不均衡,因此就引入了虛擬節點的概念,通過把三個節點加上id字尾等方式,每個節點算出n個雜湊值,均勻的放在雜湊環上,這樣對於資料算出的雜湊值,能夠比較雜湊的分布(詳見下面**中的replica)
通過這種演算法做資料分布,在增減節點的時候,可以大大減少資料的遷移規模。
3、虛擬節點
一致性雜湊演算法在服務節點太少時,容易因為節點分部不均勻而造成資料傾斜問題。例如我們的系統中有兩台伺服器,其環分布如下:
此時必然造成大量資料集中到server 1上,而只有極少量會定位到server 2上。為了解決這種資料傾斜問題,一致性雜湊演算法引入了虛擬節點機制,即對每乙個服務節點計算多個雜湊,每個計算結果位置都放置乙個此服務節點,稱為虛擬節點。具體做法可以在伺服器ip或主機名的後面增加編號來實現。例如上面的情況,我們決定為每台伺服器計算三個虛擬節點,於是可以分別計算「memcached server 1#1」、「memcached server 1#2」、「memcached server 1#3」、「memcached server 2#1」、「memcached server 2#2」、「memcached server 2#3」的雜湊值,於是形成六個虛擬節點:
一致性雜湊演算法
好吧,我們決定打破這種基於資料項商業邏輯的劃分思維,來考慮一種基於 key 的劃分方式,這有些類似於後面介紹的資料庫水平分割槽 sharding 我們需要設計一種不依賴資料項內容的雜湊演算法,將所有資料項的 key 均衡分配在這三颱快取伺服器上。乙個簡單而有效的方法是 取餘 運算,這就像打撲克時的發...
一致性雜湊演算法
在分布式系統中,如果某業務可以由多個相同的節點處理,很容易想到用hash的方式將業務請求分散到這些節點處理,如果有n個節點,計算方法為 hash id n。如果只是簡單的計算,不涉及使用者狀態,這是乙個簡單有效的方案。如果節點的計算涉及使用者狀態,比如維護購物車 memcache快取服務等,好像也沒...
一致性雜湊演算法
判定好壞的四個定義 1 平衡性 balance 平衡性是指雜湊的結果能夠盡可能分布到所有的緩衝中去,這樣可以使得所有的緩衝空間都得到利用。很多雜湊演算法都能夠滿足這一條件。2 單調性 monotonicity 單調性是指如果已經有一些內容通過雜湊分派到了相應的緩衝中,又有新的緩衝加入到系統中。雜湊的...