memcached講解

jopen 8年前發布 | 9K 次閱讀 緩存服務器 memcached

memcached的分布式主要體現在client端,對于server端,僅僅是部署多個memcached server組成集群,每個server獨自維護自己的數據(互相之間沒有任何通信),通過daemon監聽端口等待client端的請求。而在client端,通過一致的hash算法,將要存儲的數據分布到某個特定的server上進行存儲,后續讀取查詢使用同樣的hash算法即可定位。

client端可以采用各種hash算法來定位server: 取模

最簡單的hash算法

targetServer = serverList[hash(key) % serverList.size]

直接用key的hash值(計算key的hash值的方法可以自由選擇,比如算法CRC32、MD5,甚至本地hash系統,如java的hashcode)模上server總數來定位目標server。這種算法不僅簡單,而且具有不錯的隨機分布特性。

但是問題也很明顯,server總數不能輕易變化。因為如果增加/減少memcached server的數量,對原先存儲的所有key的后續查詢都將定位到別的server上,導致所有的cache都不能被命中而失效。我們無法對服務器進行簡單的增加和減少。

由于簡單的hash算法沒有良好的擴展性,我們下面來介紹一種更好的方法:一致性hash

相對于取模的算法,一致性hash算法除了計算key的hash值外,還會計算每個server對應的hash值,然后將這些hash值映射到一個有限的值域上(比如0~2^32)。通過尋找hash值大于hash(key)的最小server作為存儲該key數據的目標server。如果找不到,則直接把具有最小hash值的server作為目標server。

為了方便理解,可以把這個有限值域理解成一個環,值順時針遞增。

如上圖所示,集群中一共有5個memcached server,已通過server的hash值分布到環中。

如果現在有一個寫入cache的請求,首先計算x=hash(key),映射到環中,然后從x順時針查找,把找到的第一個server作為目標server來存儲cache,如果超過了2^32仍然找不到,則命中第一個server。比如x的值介于A~B之間,那么命中的server節點應該是B節點

可以看到,通過這種算法,對于同一個key,存儲和后續的查詢都會定位到同一個memcached server上。

那么它是怎么解決增/刪server導致的cache不能命中的問題呢?

假設,現在增加一個server F,如下圖

此時,cache不能命中的問題仍然存在,但是只存在于B~F之間的位置(由C變成了F),其他位置(包括F~C)的cache的命中不受影響(刪除server的情況類似)。盡管仍然有cache不能命中的存在,但是相對于取模的方式已經大幅減少了不能命中的cache數量。

虛擬節點

但是,這種算法相對于取模方式也有一個缺陷:當server數量很少時,很可能他們在環中的分布不是特別均勻,進而導致cache不能均勻分布到所有的server上。

一共有3臺server – 1,2,4。命中4的幾率遠遠高于1和2。

為解決這個問題,需要使用虛擬節點的思想:為每個物理節點(server)在環上分配100~200個點,這樣環上的節點較多,就能抑制分布不均勻。

當為cache定位目標server時,如果定位到虛擬節點上,就表示cache真正的存儲位置是在該虛擬節點代表的實際物理server上。

另外,如果每個實際server的負載能力不同,可以賦予不同的權重,根據權重分配不同數量的虛擬節點。

通過這種方式我們很好的能夠增加刪除我們的緩存服務器。

來自: http://www.cnblogs.com/newbalanceteam/p/5115025.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!