1、memcache啓動參數
memcached -h
memcached 1.4.20
-p <num> TCP端口,默認爲11211,可以不設置
-U <num> UDP端口,默認爲11211,0爲關閉
-s <file> UNIX socket-a <mask> access mask for UNIX socket, in octal (default: 0700)
-l <addr> 監聽的 IP 地址,本機可以不設置此參數
-d 以守護程序(daemon)方式運行
-u 指定用戶,如果當前爲 root ,需要使用此參數指定用戶
-m <num> 最大內存使用,單位MB。默認64MB
-M 禁止LRU策略,內存耗盡時返回錯誤,而不是刪除項
-c <num> 最大同時連接數,默認是1024
-v verbose (print errors/warnings while in event loop)
-vv very verbose (also print client commands/reponses)
-vvv extremely verbose (also print internal state transitions)
-h 幫助信息
-i print memcached and libevent license
-P <file> 保存PID到指定文件
-f <factor> 增長因子,默認1.25
-n <bytes> 初始chunk=key+suffix+value+32結構體,默認48字節
-L 啓用大內存頁,可以降低內存浪費,改進性能
-t <num> 線程數,默認4。由於memcached採用NIO,所以更多線程沒有太多作用
-R 每個event連接最大併發數,默認20
-C 禁用CAS命令(可以禁止版本計數,減少開銷)
-b Set the backlog queue limit (default: 1024)
-B Binding protocol-one of ascii, binary or auto (default)
-I 調整分配slab頁的大小,默認1M,最小1k到128M
2、理解memcached的內存存儲機制
2.1分配機制
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的組。
2.2、新數據申請具體過程如下:
每個slab只存儲大於其上一個slab中chunk的size並小於或者等於自己size的數據。memcached根據收到的數據的大小,選擇最適合數據大小的slab。每個chunk都是上一個slab的chunk的大小的1.25倍。可通過-f修改增長因子。
2.3內存浪費問題
每個slab中的chunk大小是一樣的,如上圖所示slab1的chunk大小是88字節,slab2是112字節。由於分配的是特定長度的內存,因此無法有效利用分配的內存。
例如,將100字節的數據緩存到128字節的chunk中,剩餘的28字節就浪費了。chunk中不僅存放緩存對象的value,而且保存了緩存對象的key,expire time, flag等詳細信息。
3、memcache狀態和性能查看
3.1命中率 :stats命令
stats
STAT pid 31150
STAT uptime 7096
STAT time 1577417038
STAT version 1.4.20
STAT libevent 1.4.13-stable
STAT pointer_size 64
STAT rusage_user 3.071533
STAT rusage_system 6.908949
STAT curr_connections 9
STAT total_connections 4987
STAT connection_structures 12
STAT reserved_fds 20
STAT cmd_get 2
STAT cmd_set 140102
STAT cmd_flush 0
STAT cmd_touch 0
STAT get_hits 2
STAT get_misses 0
STAT delete_misses 0
STAT delete_hits 0
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT touch_hits 0
STAT touch_misses 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 280231309
STAT bytes_written 3977877
STAT limit_maxbytes 10485760
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT hash_power_level 16
STAT hash_bytes 524288
STAT hash_is_expanding 0
STAT malloc_fails 0
STAT bytes 957022
STAT curr_items 451
STAT total_items 140102
STAT expired_unfetched 0
STAT evicted_unfetched 130699
STAT evictions 130699
STAT reclaimed 0
STAT crawler_reclaimed 0
命中率=get_hits / (get_hits + get_misses)
3.2觀察各slab的items的情況:Stats items命令
stats items
STAT items:15:number 451
STAT items:15:age 4133
STAT items:15:evicted 129549
STAT items:15:evicted_nonzero 129549
STAT items:15:evicted_time 1
STAT items:15:outofmemory 0
STAT items:15:tailrepairs 0
STAT items:15:reclaimed 0
STAT items:15:expired_unfetched 0
STAT items:15:evicted_unfetched 129549
STAT items:15:crawler_reclaimed 0
主要參數說明:
outofmemory | slab class爲新item分配空間失敗的次數。這意味着你運行時帶上了-M或者移除操作失敗 |
number | 存放的數據總數 |
age | 存放的數據中存放時間最久的數據已經存在的時間,以秒爲單位 |
evicted | 不得不從LRU中移除未過期item的次數 |
evicted_time | 自最後一次清除過期item起所經歷的秒數,即最後被移除緩存的時間,0表示當前就有被移除,用這個來判斷數據被移除的最近時間 |
evicted_nonzero | 沒有設置過期時間(默認30天),但不得不從LRU中移除該未過期的item的次數 |
LRU策略不是針對所有的slabs,而是隻針對新數據應該被放入的slab。
3.3 觀察各slabs的情況:stats slabs命令
從Stats items中如果發現有異常的slab,則可以通過stats slabs查看下該slab是不是內存分配的確有問題。
stats slabs
STAT 12:chunk_size 1184
STAT 12:chunks_per_page 885
STAT 12:total_pages 10
STAT 12:total_chunks 8850
STAT 12:used_chunks 0
STAT 12:free_chunks 8850
STAT 12:free_chunks_end 0
STAT 12:mem_requested 0
STAT 12:get_hits 2
STAT 12:cmd_set 10102
STAT 12:delete_hits 0
STAT 12:incr_hits 0
STAT 12:decr_hits 0
STAT 12:cas_hits 0
STAT 12:cas_badval 0
STAT 12:touch_hits 0
STAT 15:chunk_size 2320
STAT 15:chunks_per_page 451
STAT 15:total_pages 1
STAT 15:total_chunks 451
STAT 15:used_chunks 451
STAT 15:free_chunks 0
STAT 15:free_chunks_end 0
STAT 15:mem_requested 957022
STAT 15:get_hits 0
STAT 15:cmd_set 130000
STAT 15:delete_hits 0
STAT 15:incr_hits 0
STAT 15:decr_hits 0
STAT 15:cas_hits 0
STAT 15:cas_badval 0
STAT 15:touch_hits 0
STAT active_slabs 2
STAT total_malloced 11524720
主要參數說明:
屬性名稱 | 屬性說明 |
---|---|
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數 |
active_slabs | 活動的slab總數 |
total_malloced | 實際已經分配的總內存數,單位爲byte,這個數值決定了memcached實際還能申請多少內存,如果這個值已經達到設定的上限(和stats settings中的maxbytes對比),則不會有新的page被分配。 |
total_chunks = used_chunks + free_chunks + free_chunks_end
3.4對象數量的統計:
stats sizes
STAT 2144 451
注意:該命令會鎖定服務,暫停處理請求。該信息返回兩列,第一列是 item 的大小,第二列是 item 的個數。
3.5查看、導出key:stats cachedump
3.5.1先列出items:
stats items
STAT items:15:number 451
STAT items:15:age 4647
STAT items:15:evicted 129549
STAT items:15:evicted_nonzero 129549
STAT items:15:evicted_time 1
STAT items:15:outofmemory 0
STAT items:15:tailrepairs 0
STAT items:15:reclaimed 0
STAT items:15:expired_unfetched 0
STAT items:15:evicted_unfetched 129549
STAT items:15:crawler_reclaimed 0
END
3.5.2通過itemid取key,上面的id是29,再加上一個參數:爲列出的長度,0爲全部列出。
stats cachedump 15 5
ITEM k99999 [2048 b; 1577416690 s]
ITEM k99998 [2048 b; 1577416690 s]
ITEM k99997 [2048 b; 1577416690 s]
ITEM k99996 [2048 b; 1577416690 s]
ITEM k99995 [2048 b; 1577416690 s]
END
導出爲文件命令
echo "stats cachedump 15 0" | nc 192.168.180.35 11211 >/home/dev/memcache.log
4、案例分析
若通過stats查看bytes並不大,但是item被驅逐嚴重,則是因爲memcache中已經被某大小的chunk佔用,無法申請到所需的chunk。可通過stats slabs和stats items進行查看分析。