假設使用redis快取資源,key值為名稱,value為該所在檔案伺服器路徑,我們需要根據名稱查詢該檔案所在檔案伺服器上的路徑,資料量大概有2000w左右,採用隨機分配規則,部署8臺快取伺服器,每台伺服器大概含有500w條資料,並且進行主從複製。
實際上,這樣也能滿足我們的要求,但如果這樣做,當我們需要訪問某個快取項時,則需要遍歷4臺快取伺服器,遍歷的過程效率太低,時間太長。我們考慮使用hashmap底層雜湊結構,按照hash值、取模規則來分配,即 hash(名稱)% n。
如果我們使用hash的方式,每一張在進行分庫的時候都可以定位到特定的伺服器。
假設我們查詢的是"a.png",由於有4臺伺服器(排除從庫),因此公式為hash(a.png) % 4 = 2 ,可知定位到了第2號伺服器,這樣的話就不會遍歷所有的伺服器,大大提公升了效能!
上述方式雖然提公升了效能,我們不再需要對整個redis伺服器進行遍歷。但使用上述hash演算法進行快取時,會出現一些缺陷,主要體現在伺服器數量變動的時候,所有快取的位置都要發生改變。
如果我們增加一台快取伺服器,那麼規則由 hash(a.png) % 4 = 2 的公式就變成了hash(a.png)% 5 = ?;減少一台快取伺服器,規則由hash(a.png) % 4 = 2 的公式就變成了hash(a.png)% 3 = ?。這種情況帶來的結果就是當伺服器數量變動時,所有快取位置都要發生改變。換句話說,當伺服器數量發生改變時,所有快取在一定時間內是失效的,當應用無法從快取中獲取資料時,則會向後端資料庫請求資料,可能會出現快取雪崩。
所以,我們應該想辦法不讓這種情況發生,但是由於上述hash演算法本身的緣故,使用取模法進行快取時,這種情況是無法避免的,為了解決這些問題,一致性hash演算法誕生了!
一致性雜湊演算法主要應用在分布式資料儲存系統中,按照一定的策略將資料盡可能均勻分布到所有的儲存節點上去,使得系統具有良好的負載均衡效能和擴充套件性。一致性hash演算法也是使用取模的方法,只不過剛才描述的取模法是對伺服器數量進行取模,而一致性hash演算法是對 2^32 取模。我們把 2^32 想象成乙個圓,整個空間按順時針方向組織,把這個由 2^32 個點組成的圓環稱為hash環。
到目前為止,我們已經把快取伺服器與hash環聯絡在了一起。接下來使用如下演算法定位資料訪問到相應伺服器:將資料key使用相同的函式hash計算出雜湊值,並確定此資料在環上的位置,從此位置沿環順時針"行走",第一台遇到的伺服器就是其應該定位到的伺服器!
如:我們有object a、object b、object c、object d四個資料物件,經過雜湊計算後,在環空間上的位置如下:
根據一致性hash演算法,資料a會被定為到node a上,b被定為到node b上,c被定為到node c上,d被定為到node d上。
假設node c不幸宕機,可以看到此時物件a、b、d不會受到影響,只有c物件被重定位到node d。
假設在系統中增加一台伺服器node x
此時物件object a、b、d不受影響,只有物件c需要重定位到新的node x 。
綜上,一致性hash演算法對於節點的增減都只需重定位環空間中的一小部分資料,具有較好的容錯性和可擴充套件性。
一致性hash演算法在服務節點太少時,容易因為節點分部不均勻而造成資料傾斜(被快取的物件大部分集中快取在某一台伺服器上)問題,如:系統中只有3臺伺服器,被快取的物件很有可能大部分集中快取在某一台伺服器上,造成資料分配不均勻。
此時必然造成大量資料集中到node a上,而只有極少量會定位到node b上。為了解決這種資料傾斜問題,我們想要均衡的將快取分布到3臺伺服器上,最好能讓這3臺伺服器盡量多的、均勻的出現在hash環上,但真實的伺服器資源只有3臺,我們考慮將現有的物理節點通過虛擬的方法複製出來,一致性hash演算法引入了虛擬節點機制,即對每乙個服務節點計算多個雜湊,每個計算結果位置都放置乙個此服務節點,這些由實際節點虛擬複製而來的節點被稱為虛擬節點。
採用虛擬節點機制,解決了服務節點少時資料傾斜的問題,hash環上的節點就越多,快取被均勻分布的概率就越大。
【參考資料】:
什麼是一致性hash演算法?
一致性雜湊演算法
了解一致性雜湊演算法
一致性雜湊演算法是為了解決普通雜湊演算法的熱點問題,當使用普通雜湊演算法來切割資料到不同的快取伺服器時。一旦快取伺服器的數量產生變化,客戶端向快取伺服器請求相應的資料就不會命中,轉而請求具體的資料庫伺服器,從而造成快取擊穿。下面我們來看一下使用普通雜湊演算法時所帶來的問題,假如我們擁有 10 臺快取...
一致性雜湊演算法
好吧,我們決定打破這種基於資料項商業邏輯的劃分思維,來考慮一種基於 key 的劃分方式,這有些類似於後面介紹的資料庫水平分割槽 sharding 我們需要設計一種不依賴資料項內容的雜湊演算法,將所有資料項的 key 均衡分配在這三颱快取伺服器上。乙個簡單而有效的方法是 取餘 運算,這就像打撲克時的發...
一致性雜湊演算法
在分布式系統中,如果某業務可以由多個相同的節點處理,很容易想到用hash的方式將業務請求分散到這些節點處理,如果有n個節點,計算方法為 hash id n。如果只是簡單的計算,不涉及使用者狀態,這是乙個簡單有效的方案。如果節點的計算涉及使用者狀態,比如維護購物車 memcache快取服務等,好像也沒...