分散式的一致性hash問題?

我們在使用memchache做分散式緩存時,通常採用一致性hash演算法加虛擬節點的策略,但我有幾個疑問,不太明白,如下:

先說明一下應用場景:分別在兩台機器上部署了memchache的一個實例,為簡化描述,標記為a,b,其中每個實例分配兩個虛擬節點,a1,a2;b1,b2;

我的問題是:

1. 在memchache客戶端,會採用某種hash演算法將各節點分布到hash環上,如 計算各memchache的ip地址 + 編號等等,但是如果某幾個節點的hash值相同怎麼辦?特別是當memchache的節點很多時,除非類似於算md5,否則很難保證不碰撞。大家是怎麼處理這種情況的?

2. memchache客戶端會維護一個node列表,如 a,a1, a2,b,b1,b2,根據要訪問的key,計算hash(key)來確定訪問哪個node。這就意味著memchache客戶端與各memchache實例之間需要建立長連接。一旦memchache客戶端檢測到某個node不可用(比如連接斷開了),則根據一致性hash演算法,自動選擇另一個node。我的問題是: 我有多個自己的業務伺服器,各自通過memchache客戶端來訪問memchache,也就是說,存在多個memchache客戶端訪問同一個memchache集群,那就存在一種不可避免的情況: memchache客戶端1與node a連接正常,但是memchache客戶端2與node a卻斷開了...總而言之,沒法保證各memchache客戶端之間維護的node列表是完全一致的,當然,這種情況並不常見,但如果出現了,該怎麼處理?是否有好的解決辦法?

第一次在知乎提問,謝謝


問題1,很少會出現這個問題的,一個是ip地址不一樣,編號不一樣,也可以用人起的名字代替IP地址,另一個是選取好的哈希演算法,甚至選取好的種子。

另外兩個節點,四個虛擬節點不覺得少了點嗎?任一節點宕機,都會導致50%數據搬家,是否用一致性哈希意義不大啊。


ip地址 + 編號會重?那至少說明你的網路已經出問題了吧。

再說「cache」這個詞的意思就是說你不一定在裡面能找到你想要的東西,斷了重連之後你就假裝自己面對的是一個剛啟動的什麼都沒有的cache,然後該咋辦咋辦。


特別是當memchache的節點很多時,除非類似於算md5,否則很難保證不碰撞。

不衝突的hash演算法是不存在的, 只要虛擬節點夠多, 保證在概率上每個真實節點的負載是相等的就好了。

存在多個memchache客戶端訪問同一個memchache集群,那就存在一種不可避免的情況: memchache客戶端1與node
a連接正常,但是memchache客戶端2與node
a卻斷開了...總而言之,沒法保證各memchache客戶端之間維護的node列表是完全一致的,

這個是經典的分散式中的partition的問題, 一致性hash演算法本身就要解決這個問題,而且得到了證明(具體證明可以去google一下一致性hash最早的論文). 這個性質叫分散性 (Spread) : 當上游的機器看到不同的下游列表時(在上線時及不穩定的網路中比較常見), 同一個請求盡量映射到少量的節點中

另外說句題外話, 這個問題和 分散式一致性 沒有任何關係. 分散式一致性英文叫做 distributed consensus. 一致性hash叫做 consistent hashing. 完全是兩回事情, 不能混為一談,一致性hash保證不了任何的分散式一致性, 只是一種降低cachemiss的負載均衡而已。


比較贊同 @陳章義的回答,補充一下個人見解。

問題的關鍵點在於「節點很多」,「hash碰撞」, 「心跳」, 「失效處理」。

1. 首先說節點不會很多

實際使用中,不只資料庫需要垂直切分,緩存也需要垂直切分,以避免在資源緊張的情況下不同業務對資源的爭搶。MC是不知道你的業務哪個最重要,也沒法屏蔽垃圾代碼。

如果你確實有如此大的業務模塊,那我覺得你其它地方早已經產生瓶頸了。

2. 其次說hash碰撞

綜上一個C段好了把,200+機器,hash碰撞概率極小了。

3. 然後是心跳

200+機器規模下,就算長連接也可接受,當然有些浪費。

一般的處理邏輯是發現節點失效,使用下一節點。

4. 失效處理

一致性哈希失效處理是有些問題,但和問題中描述的不太相同。

應該盡量確保服務組件和MC集群之間網路的穩定性。緩存肯定是就近部署的,要不然還有啥用。

而且可以這麼理解,如果你集群內部網路都出問題了,那對外提供的服務。。。

其實比較容易出現的問題是漂移的問題:某個節點失效了,緩存都漂到下個節點了;然後一會它又恢復了,這時候它就有臟數據了。

解決辦法一是每個節點引入集群。

不用集群想徹底解決這個問題,可能需要引入第三方健康檢查組件,如Consul,發現節點不穩定立即刪除下線。

5. 緩存命中率及單一熱點問題

一致性哈希解決的是某節點宕機後緩存失效的問題,只會導致相鄰節點負載增加。但是因為宕機後需要重新從資料庫讀取,會導致此時緩存命中率下降及db壓力增加。

也無法避免單一熱點問題。某一數據被海量請求,不論怎麼哈希,哈希環多大,數據只存在一個節點,早晚有被打垮的時候。

此時的解決策略是每個節點主備或主主集群。


推薦閱讀:

國內優秀的響應式WEB網站有哪些?
怎麼用dht網路標誌獲得bt種子或磁力鏈接?
Clojure 適合個人用來做 Web 快速開發么?
如果打算走網路這條路,考CCNA和CCNP是不是很有必要?
樹莓派2性能如何?

TAG:分散式存儲 | 計算機網路 | Memcached | 網路編程 | 分散式一致性 |