在分布式系統中,如果某業務可以由多個相同的節點處理,很容易想到用hash的方式將業務請求分散到這些節點處理,如果有n個節點,計算方法為:hash(id)%n。
如果只是簡單的計算,不涉及使用者狀態,這是乙個簡單有效的方案。如果節點的計算涉及使用者狀態,比如維護購物車、memcache快取服務等,好像也沒什麼問題,只要用同乙個資料做id,上述hash的結果也保持不變。但如果節點數量發生變化,比如由於業務量的增大而增加節點或由於機器宕機而減少節點,上述hash的結果就不一樣了。若增加2個節點,某id原處理節點為hash(id)%n,新的處理節點就變成了hash(id)% (n +2),可能會將大量id的處理節點打亂重新分配,就會發現之前某節點儲存的使用者資料用不到了,而新的處理節點根本沒有這些資料。在這段時間內,這些使用者的狀態受到破壞,如果是購物車,車裡的東西都沒了,如果是快取服務,之前的快取都消失了,起不到快取的效果。可能需要使用者重新登入,可能需要從資料庫更新快取,可能由此引入新的問題。
一致性雜湊在一定程度上緩解了這個問題,步驟為:
1.將整個雜湊值空間組織成乙個虛擬圓環,假設某雜湊函式h的值空間為0-(2^32-1),即32位無符號整數
2.將各節點用h函式雜湊,可以將伺服器的ip或主機名作為關鍵字雜湊,這樣每個節點就能確定其在雜湊環上的位置
3.將id用h函式對映到雜湊空間的乙個值,沿該值向後,將遇到的第乙個節點做為處理節點
下圖中,若某id的hash值落在node1和node2各自hash值的中間位置,則此id對應的業務請求由node2處理。
當增加服務節點時,只會影響與之相鄰的某一節點,其他節點不受影響。如果在node2和node4之間增加乙個node5,則只有node4處理的部分id(hash值落在node2之後、node5之前的那部分id)變為由node5來處理,其他節點處理的id不變。比開頭所述的簡單hash方式有了很大的改善。
如果節點數不多,將這些節點對映到值空間之後,分布可能會很不均勻,必然會造成個別節點處理的id數量遠大於其他節點,這就起不到負載均衡的效果。這可以通過引入虛擬節點的方式解決,即對每乙個節點計算多個hash值,盡量保證這些hash值比較均勻的分布在值空間中。當根據id查詢節點時,找到的是虛擬節點,然後再根據虛擬節點查詢對應的真實節點。多了一次查詢的過程。
memcached的客戶端庫libmemcached已經支援此演算法。
以上整理自網際網路,做個筆記。
參考: 1.
2.
一致性雜湊演算法
好吧,我們決定打破這種基於資料項商業邏輯的劃分思維,來考慮一種基於 key 的劃分方式,這有些類似於後面介紹的資料庫水平分割槽 sharding 我們需要設計一種不依賴資料項內容的雜湊演算法,將所有資料項的 key 均衡分配在這三颱快取伺服器上。乙個簡單而有效的方法是 取餘 運算,這就像打撲克時的發...
一致性雜湊演算法
判定好壞的四個定義 1 平衡性 balance 平衡性是指雜湊的結果能夠盡可能分布到所有的緩衝中去,這樣可以使得所有的緩衝空間都得到利用。很多雜湊演算法都能夠滿足這一條件。2 單調性 monotonicity 單調性是指如果已經有一些內容通過雜湊分派到了相應的緩衝中,又有新的緩衝加入到系統中。雜湊的...
一致性雜湊演算法
我們的memcache客戶端 這裡我看的spymemcache的原始碼 使用了一致性hash演算法ketama進行資料儲存節點的選擇。與常規的hash演算法思路不同,只是對我們要儲存資料的key進行hash計算,分配到不同節點儲存。一致性hash演算法是對我們要儲存資料的伺服器進行hash計算,進而...