一直在使用Memcache,但是對其内部的問題,如它記憶體是怎麼樣被使用的,使用一段時間後想看看一些狀态怎麼樣?一直都不清楚,查了又忘記,現在整理出該篇文章,友善自己查閱。本文不涉及安裝、操作。有興趣的同學可以檢視之前寫的文章和Google。
1:參數
上面加粗的參數,需要重點關注,正常啟動的例子:
可以通過指令檢視所有參數:stats settings

2:了解memcached的記憶體存儲機制
Memcached預設情況下采用了名為Slab Allocator的機制配置設定、管理記憶體。在該機制出現以前,記憶體的配置設定是通過對所有記錄簡單地進行malloc和free來進行的。但是,這種方式會導緻記憶體碎片,加重作業系統記憶體管理器的負擔,最壞的情況下,會導緻作業系統比memcached程序本身還慢。Slab Allocator就是為解決該問題而誕生的。
Slab Allocator的基本原理是按照預先規定的大小,将配置設定的記憶體以page為機關,預設情況下一個page是1M,可以通過-I參數在啟動時指定,分割成各種尺寸的塊(chunk), 并把尺寸相同的塊分成組(chunk的集合),如果需要申請記憶體時,memcached會劃分出一個新的page并配置設定給需要的slab區域。page一旦被配置設定在重新開機前不會被回收或者重新配置設定,以解決記憶體碎片問題。
Page
配置設定給Slab的記憶體空間,預設是1MB。配置設定給Slab之後根據slab的大小切分成chunk。
Chunk
用于緩存記錄的記憶體空間。
Slab Class
特定大小的chunk的組。
Memcached并不是将所有大小的資料都放在一起的,而是預先将資料空間劃分為一系列slabs,每個slab隻負責一定範圍内的資料存儲。memcached根據收到的資料的大小,選擇最适合資料大小的slab。memcached中儲存着slab内空閑chunk的清單,根據該清單選擇chunk,然後将資料緩存于其中。
如圖所示,每個slab隻存儲大于其上一個slab的size并小于或者等于自己最大size的資料。例如:100位元組大小的字元串會被存到slab2(88-112)中,每個slab負責的空間是不等的,memcached預設情況下下一個slab的最大值為前一個的1.25倍,這個可以通過修改-f參數來修改增長比例。
Slab Allocator解決了當初的記憶體碎片問題,但新的機制也給memcached帶來了新的問題。chunk是memcached實際存放緩存資料的地方,這個大小就是管理它的slab的最大存放大小。每個slab中的chunk大小是一樣的,如上圖所示slab1的chunk大小是88位元組,slab2是112位元組。由于配置設定的是特定長度的記憶體,是以無法有效利用配置設定的記憶體。例如,将100位元組的資料緩存到128位元組的chunk中,剩餘的28位元組就浪費了。這裡需要注意的是chunk中不僅僅存放緩存對象的value,而且儲存了緩存對象的key,expire time, flag等詳細資訊。是以當set 1位元組的item,需要遠遠大于1位元組的空間存放。
memcached在啟動時指定 Growth Factor因子(通過-f選項), 就可以在某種程度上控制slab之間的差異。預設值為1.25。
slab的記憶體配置設定具體過程如下:
Memcached在啟動時通過-m參數指定最大使用記憶體,但是這個不會一啟動就占用完,而是逐漸配置設定給各slab的。如果一個新的資料要被存放,首先選擇一個合适的slab,然後檢視該slab是否還有空閑的chunk,如果有則直接存放進去;如果沒有則要進行申請,slab申請記憶體時以page為機關,無論大小為多少,都會有1M大小的page被配置設定給該slab(該page不會被回收或者重新配置設定,永遠都屬于該slab)。申請到page後,slab會将這個page的記憶體按chunk的大小進行切分,這樣就變成了一個chunk的數組,再從這個chunk數組中選擇一個用于存儲資料。若沒有空閑的page的時候,則會對改slab進行LRU,而不是對整個memcache進行LRU。
以上大緻講解了memcache的記憶體配置設定政策,下面來說明如何檢視memcache的使用狀況。
3,memcache狀态和性能檢視
① 命中率 :stats指令
按照下面的圖來解讀分析
get_hits表示讀取cache命中的次數,get_misses是讀取失敗的次數,即嘗試讀取不存在的緩存資料。即:
命中率=get_hits / (get_hits + get_misses)
命中率越高說明cache起到的緩存作用越大。但是在實際使用中,這個命中率不是有效資料的命中率,有些時候get操作可能隻是檢查一個key存在不存在,這個時候miss也是正确的,這個命中率是從memcached啟動開始所有的請求的綜合值,不能反映一個時間段内的情況,是以要排查memcached的性能問題,還需要更詳細的數值。但是高的命中率還是能夠反映出memcached良好的使用情況,突然下跌的命中率能夠反映大量cache丢失的發生。
② 觀察各slab的items的情況:Stats items指令
主要參數說明:
outofmemory
slab class為新item配置設定空間失敗的次數。這意味着你運作時帶上了-M或者移除操作失敗
number
存放的資料總數
age
存放的資料中存放時間最久的資料已經存在的時間,以秒為機關
evicted
不得不從LRU中移除未過期item的次數
evicted_time
自最後一次清除過期item起所經曆的秒數,即最後被移除緩存的時間,0表示目前就有被移除,用這個來判斷資料被移除的最近時間
evicted_nonzero
沒有設定過期時間(預設30天),但不得不從LRU中稱除該未過期的item的次數
因為memcached的記憶體配置設定政策導緻一旦memcached的總記憶體達到了設定的最大記憶體,表示所有的slab能夠使用的page都已經固定,這時如果還有資料放入,将導緻memcached使用LRU政策剔除資料。而LRU政策不是針對所有的slabs,而是隻針對新資料應該被放入的slab,例如有一個新的資料要被放入slab 3,則LRU隻對slab 3進行,通過stats items就可以觀察到這些剔除的情況。
注意evicted_time:并不是發生了LRU就代表memcached負載過載了,因為有些時候在使用cache時會設定過期時間為0,這樣緩存将被存放30天,如果記憶體滿了還持續放入資料,而這些為過期的資料很久沒有被使用,則可能被剔除。把evicted_time換算成标準時間看下是否已經達到了你可以接受的時間,例如:你認為資料被緩存了2天是你可以接受的,而最後被剔除的資料已經存放了3天以上,則可以認為這個slab的壓力其實可以接受的;但是如果最後被剔除的資料隻被緩存了20秒,不用考慮,這個slab已經負載過重了。
通過上面的說明可以看到目前的memcache的slab1的狀态:
③ 觀察各slabs的情況:stats slabs指令
從Stats items中如果發現有異常的slab,則可以通過stats slabs檢視下該slab是不是記憶體配置設定的确有問題。
屬性名稱
屬性說明
chunk_size
目前slab每個chunk的大小
chunk_per_page
每個page能夠存放的chunk數
total_pages
配置設定給目前slab的page總數,預設1個page大小1M,可以計算出該slab的大小
total_chunks
目前slab最多能夠存放的chunk數,應該等于chunck_per_page * total_page
used_chunks
已經被占用的chunks總數
free_chunks
過期資料空出的chunk但還沒有被使用的chunk數
free_chunks_end
新配置設定的但是還沒有被使用的chunk數
這裡需要注意:total_pages 這個是目前slab總共配置設定大的page總數,如果沒有修改page的預設大小的情況下,這個數值就是目前slab能夠緩存的資料的總大小(機關為M)。如果這個slab的剔除非常嚴重,一定要注意這個slab的page數是不是太少了。還有一個公式:
total_chunks = used_chunks + free_chunks + free_chunks_end
另外stats slabs還有2個屬性:
active_slabs
活動的slab總數
total_malloced
實際已經配置設定的總記憶體數,機關為byte,這個數值決定了memcached實際還能申請多少記憶體,如果這個值已經達到設定的上限(和stats settings中的maxbytes對比),則不會有新的page被配置設定。
④ 對象數量的統計:stats sizes
注意:該指令會鎖定服務,暫停處理請求。該指令展示了固定chunk大小中的items的數量。也可以看出slab1(96byte)中有多少個chunks。
⑤ 檢視、導出key:stats cachedump
在進入memcache中,大家都想檢視cache裡的key,類似redis中的keys *指令,在memcache裡也可以檢視,但是需要2步完成。
一是先列出items:
二是通過itemid取key,上面的id是29,再加上一個參數:為列出的長度,0為全部列出。
如何導出key呢?這裡就需要通過 echo ... nc 來完成了
在導出的時候需要注意的是:cachedump指令每次傳回的資料大小隻有2M,這個是memcached的代碼中寫死的一個數值,除非在編譯前修改。
⑥ 另一個監控工具:memcached-tool,一個perl寫的工具:memcache_tool.pl。
View Code
解釋:
列
含義
#
slab class編号
Item_Size
chunk大小
Max_age
LRU内最舊的記錄的生存時間
pages
配置設定給Slab的頁數
count
Slab内的記錄數、chunks數、items數、keys數
Full?
Slab内是否含有空閑chunk
Evicted
從LRU中移除未過期item的次數
Evict_Time
最後被移除緩存的時間,0表示目前就有被移除
OOM
-M參數?
本文轉自 sshpp 51CTO部落格,原文連結:http://blog.51cto.com/12902932/1927048,如需轉載請自行聯系原作者