幾個重要概念
Slab
memcached通過slab機制進行內存的分配和回收,slab是一個內存塊,它是memcached一次申請內存的最小單位,。在啟動memcached的時候一般會使用參數-m指定其可用內存,但是并不是在啟動的那一刻所有的內存就全部分配出去了,只有在需要的時候才會去申請,而且每次申請一定是一個slab。Slab的大小固定為1MB(1MB=1024KB=1024×1024B=1048576B,1048576字節),一個slab由若干個大小相等的chunk組成。
Slab的分類
根據chunk的大小而將Slab分為不同的類,chunk大小的增幅由增長因子factor決定。根據memcached版本的不同而分類也各有不同,-vv查詢分類。
Chunk
chunk是Slab的組成單位,每個Slab都被分割成大小相等的chunk,分割Slab時,不夠一個chunk大小的內存空間將被不可以避免的浪費(內存碎片化)。每個chunk中都保存了一個item結構體,item結構體由屬性域和數據域組成,數據域中有一個變長數據data,是真正存儲緩存記錄key和value的地方。
圖memcached Slab 分類示意圖
源碼
typedef struct _stritem {
//屬性域
struct _stritem *next;
struct _stritem *prev;
......
//數據域
union {
uint64_t cas;
char end;
} data[];
} item;
Chunk的計算
對于Slab 分類 i,求Slab 分類 i中的chunk的大小:
chunkSize = (default_size + item_size)*f^(i-1) + CHUNK_ALIGN_BYTES
各參數含義:
l i,分類
l default_size,默認大小為48字節,也就是item結構體中數據域的大小為48字節,可以通過-n參數來調節其大小
l item_size, item結構體的長度,固定為32字節
l f,factor,增長因子,是chunk變化大小的因素,默認值為1.25,調節f可以改變chunk的增幅,在啟動時可以使用-f來指定
l CHUNK_ALIGH_BYTES 是一個長常量值,用來保證chunk的大小是這個常量值的整數倍,防止越界。CHUNK_ALIGH_BYTES 大小為sizeof(void *)
例如:void *的長度在不同系統上不一樣,在32位機器上,sizeof(void *)值為4
所以,在32為的系統中,Slab 分類1中chunk的大小為:
chunkSize1 = (48 + 32)* 1.25^(1-1) + 4 = 84(有待驗證)
從chunkSize的計算公式可以看出,可以通過調節-n,-f參數來調整chunk的大小,這也是實際中mecahced調優的關鍵,合理的調節-n,-f參數以充分利用內存資源,盡可能的減少內存碎片化。
內存分配
當我們通過add命令向memcached中添加一條記錄的時候,memcached會根據數據的大小選擇合適的slab,memcached維護著slab中空閑的chunk列表,并從中選擇一塊分配給要添加的記錄。
如要存的item大小為100byte,chunk大小為80byte的slab將存不下,而chunk大小為120byte的slab又有剩余,此時memcached會將數據存到chunk大小為120byte的slab中。而剩余的20byte空間將不可避免的浪費。
需要注意的是,當chunk大小為120byte的slab已經滿時,memcached并不會尋找更大chunk的slab,如chunk大小為140byte的slab來存儲,而是把chunk大小為120byte的slab中的舊數據踢掉。
增長因子調優
memcached 在啟動時可以通過f 選項指定增長因子,默認為1.25。增長因子的不同,chunk大小也不同,應根據實際情況,指定合理的增長因子避免過多的內存空間浪費。
過期數據惰性刪除
Memcached中,當某個chunk 中的數據過期后,并不會馬上從內存中刪除,因此,使用stats 統計時,curr_item中仍然有其信息,直到新的數據占用該chunk ;當試圖去get改數據時,先判斷是否過期,如果過期則返回空并清空chunk,curr_item減1。過期數據不會馬上刪除,這種機制稱為lazy expiration,即惰性失效,好處是不需要另外去檢查數據是否失效,節省了CUP的檢測成本。
LRU刪除機制
和操作系統內存管理類似,memcached數據刪除機制使用的是“最近最少使用”機制(Least Recently Used)進行數據剔除,memcached通過維護一個計數器,來判斷最近誰最少被使用,當有新的數據進來時,最近最少用的數據將被剔除。
memcached使用三十二位元的循環冗余校驗(CRC-32)計算鍵值后,將數據分散在不同的機器上。當chunk滿了以后,接下來新增的數據會以LRU機制替換掉。
即使某個key被設置永久有效期,也一樣會被踢出來,即永久數據被踢現象。
參考文檔:
http://kenby.iteye.com/blog/1423989
http://www.dexcoder.com/selfly/article/2248
http://www.dexcoder.com/selfly/series/63
http://www.cnblogs.com/luluping/archive/2009/01/14/1375456.html
文章列表