memcached的內存分配沒有用到c語言中自帶的malloc函數,由於這個函數分配內存的時候效率很低,對於這種要求快速響應,對效率要求很是高的緩存軟件來講很是不合適。node
memcached用的是本身的一套內存分配方法,叫作slab allocation。算法
***64位的操做系統能分配 2GB 以上的內存。32位的操做系統中,每一個進程最多隻能使用 2GB 內存。數據庫
***若是想緩存更多的數據,建議仍是開闢更多的memcache進程(不一樣端口)或者使用分佈式memcache進行緩存,將數據緩存到不一樣的物理機或者虛擬機上。數組
***memcached啓動時指定的內存分配(如:-m 64)是memcached用於保存數據的量,不包括memcached自己佔用的內存、以及爲了保存數據而設置的管理空間。所以,memcached進程的實際內存分配量要比指定的容量要大。緩存
Memcache進程啓動,在內存開闢了連續的區域。我們用上面的圖形來舉例,這段連續的區域就好像上面的slab1+slab2+slab3+……+slab(n).分配區域相同的構成了slab(分片組)。Slab下面可不直接就是存儲區域片(就是圖中的chunks)了。而是page,若是一個新的緩存數據要被存放,memcached首先選擇一個合適的slab,而後查看該slab是否還有空閒的chunk,若是有則直接存放進去;若是沒有則要進行申請。服務器
slab申請內存時以page爲單位,因此在放入第一個數據,不管大小爲多少,都會有1M大小的page被分配給該slab。申請到page後,slab會將這個page的內存按chunk的大小進行切分,這樣就變成了一個chunk的數組,在從這個chunk數組中選擇一個用於存儲數據。在Page中才是一個個小存儲單元——chunks,一個page默認1mb,那麼能夠放多少個88字節單位的chunks呢?1024*1024/88約等於11915個。若是放入記錄是一個100字節的數據,那麼在88字節的chunks和112字節的chunks中如何調配呢。答案固然是緊着大的用,不可能將請求過來的數據再作個分解、分離存儲、合併讀取吧。這樣也就帶來了一個小問題,仍是有空間浪費掉了。112-100=12字節,這12字節就浪費了。負載均衡
Memcache藉助了操做系統的libevent工具作高效的讀寫。libevent是個程序庫,它將Linux的epoll、BSD類操做系統的kqueue等事件處理功能封裝成統一的接口。即便對服務器的鏈接數增長,也能發揮高性能。memcached使用這個libevent庫,所以能在Linux、BSD、Solaris等操做系統上發揮其高性能。Memcache號稱能夠接受任意數量的鏈接請求。事實真的是這樣嗎?分佈式
**一個memcahced進程會預先將本身劃分爲若干個slab,slab得數量是有限的,跟進程配置的內存無關,跟-f(增加因子),-I(page大小),-n(初始chunk大小)有關。memcached
**slab的數量最大是200(當指定-f 1.0001)時,增加因子越大,slab越少,-f 不能小於1。函數
**能夠經過-I指定page的大小,單位是byte,page默認是1M,最小須要1024byte, page值設置的越大slab越多。
**-n(最小分配空間):即初始chunk的大小,默認是48,此時初始chunk的大小是96,(注意並非2倍的關係,當設置爲50時,第一個chunk的大小是104),-n越大slab越少。
**一個slab能夠申請多個page,當前slab下沒有數據時不會分配page。
推薦:對slab,page,chunk解釋的較詳細:http://tank.blogs.tkiicpp.com/2010/12/14/memcache%E5%86%85%E5%AD%98%E5%88%86%E9%85%8D%E7%AD%96%E7%95%A5/
存儲過程分析
假設咱們如今往memcache中存儲一個緩存記錄,首先在使用memcache客戶端程序的時候要制定一個初始化的服務機器路由表,好比PHP的客戶端程序
$mc = new Memcache();
$mc->addserver('192.168.1.110',11211);
$mc->addserver('192.168.1.120',11211);
$mc->addserver('192.168.1.130',11211);
那麼在作存儲的時候memcache客戶端程序會hash出一個碼,以後再根據路由表去將請求轉發給memcache服務端,也就是說memcache的客戶端程序至關於作了一個相似負載均衡的功能。
而memcache在server上面的進程僅僅負責監聽服務和接受請求、存儲數據的做用。分發不歸他管。因此這麼看的話,散列到每臺memcache服務機器,讓每臺機器分佈存儲得均勻是客戶端代碼實現的一個難點。這個時侯Hash散列算法就顯得格外重要了吧。
讀取過程分析
理解了memcache的存儲就不難理解memcache的讀取緩存的過程了。在讀取的時候也是根據key算出一個hash,以後在算出指定的路由物理機位置,再將請求分發到服務機上。
memcache分佈式讀寫的存儲方式有利有弊。若是node2宕機了,那麼node2的緩存數據就沒了,那麼還得先從數據庫load出來數據,從新根據路由表(此時只有node1和node3),從新請求到一個緩存物理機上,在寫到重定向的緩存機器中。災難恢復已經實現得較爲完備。弊端就是維護這麼一個高可用緩存,成本有點兒大了。爲了存儲更多的數據,這樣作是否利大於弊,仍是得看具體的應用場景再定。