Memcached深刻分析及內存調優

到這裏memcached的初步使用咱們已經沒問題了,可是瞭解一些它內部的機制仍是十分必要的,這直接涉及到你可否把memcached給真正「用好」。 html

Memcached的守護進程機制使用的是Unix下的daemon,Socket則使用了非阻塞(non-blocked)高性能的NIO,事件處理上你們都已經知道了,是基於libevent,支持異步的事件處理。 ubuntu

最主要的是要知道它的內存管理機制,使用以下命令啓動memcached: xcode

liyd@ubuntu:~$ memcached -d -m256 -p11211 -u liyd

這裏咱們分配了256M的內存給memcached,那麼memcached又是怎麼樣來分配內存的呢?先看下圖: 緩存

QQ圖片20150427203745

Memcached在分配內存時是以Page爲單位的,默認狀況下一個Page是1M,內部是一個個chunk,當chunk的大小等於Page大小時也就是Memcached所能存儲的最大數據大小了,能夠在啓動時經過-l來指定它,最大能夠支持128M。 網絡

Memcached並非將全部大小的數據都存放在一塊兒的,而是將內存空間劃分爲一個個的slab,每一個slab只負責必定範圍內的數據。上圖中,slab1只負責96bytes的數據,slab2負責120bytes的數據。 session

在存儲數據時,若是這個item對應的slab尚未建立則申請一個page的內存,將這個page按照所在slab中chunk的大小進行分割,而後將item存入。 dom

若是已經建立存在了,判斷對應的slab是否用完,沒用完直接存儲。 異步

若是對應的slab已經用完了,看內存是否用完,沒用完會申請一個新的page進行分割存儲,用完了則直接進行LRU。 socket

那麼咱們怎麼樣來查看各個slab的情況及裏面的chunk大小呢? tcp

在前面的啓動參數中咱們發現有-v –vv -vvv三個選項,通常咱們用的最多的是-vv:

liyd@ubuntu:~$ memcached -d -m256 -p11211 -u liyd -vv
liyd@ubuntu:~$ slab class 1: chunk size        96 perslab   10922
slab class 2: chunk size       120 perslab    8738
slab class 3: chunk size       152 perslab    6898
slab class 4: chunk size       192 perslab    5461
slab class 5: chunk size       240 perslab    4369
slab class 6: chunk size       304 perslab    3449
slab class 7: chunk size       384 perslab    2730
slab class 8: chunk size       480 perslab    2184
slab class 9: chunk size       600 perslab    1747
slab class 10: chunk size       752 perslab    1394
slab class 11: chunk size       944 perslab    1110
slab class 12: chunk size      1184 perslab     885
slab class 13: chunk size      1480 perslab     708
slab class 14: chunk size      1856 perslab     564
slab class 15: chunk size      2320 perslab     451
slab class 16: chunk size      2904 perslab     361
slab class 17: chunk size      3632 perslab     288
slab class 18: chunk size      4544 perslab     230
slab class 19: chunk size      5680 perslab     184
slab class 20: chunk size      7104 perslab     147
slab class 21: chunk size      8880 perslab     118
slab class 22: chunk size     11104 perslab      94
slab class 23: chunk size     13880 perslab      75
slab class 24: chunk size     17352 perslab      60
slab class 25: chunk size     21696 perslab      48
slab class 26: chunk size     27120 perslab      38
slab class 27: chunk size     33904 perslab      30
slab class 28: chunk size     42384 perslab      24
slab class 29: chunk size     52984 perslab      19
slab class 30: chunk size     66232 perslab      15
slab class 31: chunk size     82792 perslab      12
slab class 32: chunk size    103496 perslab      10
slab class 33: chunk size    129376 perslab       8
slab class 34: chunk size    161720 perslab       6
slab class 35: chunk size    202152 perslab       5
slab class 36: chunk size    252696 perslab       4
slab class 37: chunk size    315872 perslab       3
slab class 38: chunk size    394840 perslab       2
slab class 39: chunk size    493552 perslab       2
slab class 40: chunk size    616944 perslab       1
slab class 41: chunk size    771184 perslab       1
slab class 42: chunk size   1048576 perslab       1
<26 server listening (auto-negotiate)
<27 send buffer was 212992, now 268435456
<28 send buffer was 212992, now 268435456
<27 server listening (udp)
<28 server listening (udp)
<27 server listening (udp)
<28 server listening (udp)
<27 server listening (udp)
<28 server listening (udp)
<27 server listening (udp)
<28 server listening (udp)

咱們看到,一共有42個slab,第一個slab中chunk大小爲96bytes,第二個爲120bytes,第三個爲152bytes,每一個slab中chunk的大小都不同,這個chunk就是memcached具體存儲數據的地方。

Memcached經過指定的成長因子(-f指定,默認1.25倍)來決定每一個slab中chunk增加的範圍,第一個slab的大小能夠經過-n來設定。

當數據進來時Memcached會選擇一個大於等於最接近的slab來進行存儲。例如當item大小爲95時將存儲到chunk爲96bytes的slab1,item大小爲97時則會存儲到chunk大小爲120的slab2.

這樣分配的好處是速度快,避免大量重複的初始化和清理操做,有效的避免了內存碎片的問題,但內存利用率上會有所浪費。

另外Memcached是懶檢測機制,當存儲在內存中的對象過時甚至是flush_all時,它並不會作檢查或刪除操做,只有在get時才檢查數據對象是否應該刪除。

刪除數據時,Memcached一樣是懶刪除機制,只在對應的數據對象上作刪除標識並不回收內存,在下次分配時直接覆蓋使用。

瞭解了Memcached的內存分配機制,如何進行調優是否是天然而然的就明白了?

應該儘可能的根據實際狀況來設定slab的chunk的初始大小和增加因子,儘可能減小內存的浪費。在某些狀況下數據的長度都會集中在一個區域,如session。甚至會有定長的狀況,如數據統計等。

還有一個重要調優的地方就是提升緩存命中率了,這個沒有固定的方法,還得具體場景作具體業務分析,須要注意的就是,Memcached中LRU的操做是基於slab而非全局,分析時最好考慮這一點,這也就是有時候內存還沒用完但數據卻被回收了的緣由。

咱們也能夠藉助相似memcached-tool這類對memcache的狀態性能分析工具來更直觀的查看memcache內部的狀態,可是功能上也比較有限,就不細講了,主要就是如下幾個命令:

#memcached-tool
#Usage: memcached-tool <host[:port]> [mode]
memcached-tool 127.0.0.1:11211 display    # shows slabs
memcached-tool 127.0.0.1:11211            # same.  (default is display)
memcached-tool 127.0.0.1:11211 stats      # shows general stats
memcached-tool 127.0.0.1:11211 dump       # dumps keys and value

如今咱們再回過頭去看Memcached的stats命令,是否是就頗有用了?這裏貼上經常使用的一些參數說明。

stats統計項:

pid Memcached進程ID
uptime Memcached運行時間,單位:秒
time Memcached當前的UNIX時間
version Memcached的版本號
rusage_user 該進程累計的用戶時間,單位:秒
rusage_system 該進程累計的系統時間,單位:秒
curr_connections 當前鏈接數量
total_connections Memcached運行以來接受的鏈接總數
connection_structures Memcached分配的鏈接結構的數量
cmd_get 查詢請求總數
get_hits 查詢成功獲取數據的總次數
get_misses 查詢成功未獲取到數據的總次數
cmd_set 存儲(添加/更新)請求總數
bytes Memcached當前存儲內容所佔用字節數
bytes_read Memcached從網絡讀取到的總字節數
bytes_written Memcached向網絡發送的總字節數
limit_maxbytes Memcached在存儲時被容許使用的字節總數
curr_items Memcached當前存儲的內容數量
total_items Memcached啓動以來存儲過的內容總數
evictions LRU釋放對象數,用來釋放內存

stats slabs區塊統計:

chunk_size chunk大小,byte chunks_per_page 每一個page的chunk數量
total_pages page數量
total_chunks chunk數量*page數量
get_hits get命中數
cmd_set set數
delete_hits delete命中數
incr_hits incr命中數
decr_hits decr命中數
cas_hits cas命中數
cas_badval cas數據類型錯誤數
used_chunks 已被分配的chunk數
free_chunks 剩餘chunk數
free_chunks_end 分完page浪費chunk數
mem_requested 請求存儲的字節數
active_slabs slab數量
total_malloced 總內存數量

被浪費內存數=(total_chunks * chunk_size) - mem_requested,若是太大,則須要調整factor

stats items數據項統計:

number 該slab中對象數,不包含過時對象
age LRU隊列中最老對象的過時時間
evicted LRU釋放對象數
evicted_nonzero 設置了非0時間的LRU釋放對象數
evicted_time 最後一次LRU秒數,監控頻率
outofmemory 不能存儲對象次數,使用-M會報錯
tailrepairs 修復slabs次數
reclaimed 使用過時對象空間存儲對象次數

stats settings查看設置:

maxbytes 最大字節數限制,0無限制
maxconns 容許最大鏈接數
tcpport TCP端口
udpport UDP端口
verbosity 日誌0=none,1=som,2=lots
oldest 最老對象過時時間
evictions on/off,是否禁用LRU
domain_socket socket的domain
umask 建立Socket時的umask
growth_factor 增加因子
chunk_size key+value+flags大小
num_threads 線程數,能夠經過-t設置,默認4
stat_key_prefix stats分隔符
detail_enabled yes/no,顯示stats細節信息
reqs_per_event 最大IO吞吐量(每event)
cas_enabled yes/no,是否啓用CAS,-C禁用
tcp_backlog TCP監控日誌
auth_enabled_sasl yes/no,是否啓用SASL驗證

原文地址:Memcached深刻分析及內存調優

相關文章
相關標籤/搜索