Memcached安装使用和源码调试
memcached官網:http://memcached.org/
一.安裝
下載
# wget?http://www.memcached.org/files/memcached-1.4.25.tar.gz
解壓
# tar xzvf memcached-1.4.25.tar.gz
#cd memcached-1.4.25
配置
#./configure --prefix=/usr/local/memcached --with-libevent=/usr
注意這里選擇libevent的位置即可? 例如你的是在–with-libevent=/usr/local/libevent/
# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
編譯安裝
# make &&?make install
---------------需要依賴安裝libevent-------------------
libevent官網?http://libevent.org/
# wget https://github.com/libevent/libevent/releases/download/release-2.0.22-stable/libevent-2.0.22-stable.tar.gz
# tar xzvf libevent-2.0.22-stable.tar.gz
# cd libevent-2.0.22-stable
# ./configure --prefix=/usr/local/libevent
# make &&?make install
----------------------------------
二.使用
啟動
# /usr/local/memcached/bin/memcached -d -m 100 -uroot -l 0.0.0.0 -p 11211 -c 512 -P /usr/local/memcached/memcached.pid
啟動參數:
memcached 1.4.2
-p <num> 監聽的TCP端口(默認: 11211)
-U <num> 監聽的UDP端口(默認: 11211, 0表示不監聽)
-s <file> 用于監聽的UNIX套接字路徑(禁用網絡支持)
-a <mask> UNIX套接字訪問掩碼,八進制數字(默認:0700)
-l <ip_addr> 監聽的IP地址。(默認:INADDR_ANY,所有地址)
-d 作為守護進程來運行。
-r 最大核心文件限制。
-u <username> 設定進程所屬用戶。(只有root用戶可以使用這個參數)
-m <num> 單個數據項的最大可用內存,以MB為單位。(默認:64MB)
-M 內存用光時報錯。(不會刪除數據)
-c <num> 最大并發連接數。(默認:1024)
-k 鎖定所有內存頁。注意你可以鎖定的內存上限。試圖分配更多內存會失敗的,所以留意啟動守護進程時所用的用戶可分配的內存上限。(不是前面的 -u <username> 參數;在sh下,使用命令"ulimit -S -l NUM_KB"來設置。)
-v 提示信息(在事件循環中打印錯誤/警告信息。)
-vv 詳細信息(還打印客戶端命令/響應)
-vvv 超詳細信息(還打印內部狀態的變化)
-h 打印這個幫助信息并退出。
-i 打印memcached和libevent的許可。
-P <file> 保存進程ID到指定文件,只有在使用 -d 選項的時候才有意義。
-f <factor> 塊大小增長因子。(默認:1.25)
-n <bytes> 分配給key+value+flags的最小空間(默認:48)
-L 嘗試使用大內存頁(如果可用的話)。提高內存頁尺寸可以減少"頁表緩沖(TLB)"丟失次數,提高運行效率。為了從操作系統獲得大內存頁,memcached會把全部數據項分配到一個大區塊。
-D <char> 使用 <char> 作為前綴和ID的分隔符。這個用于按前綴獲得狀態報告。默認是":"(冒號)。如果指定了這個參數,則狀態收集會自動開啟;如果沒指定,則需要用命令"stats detail on"來開啟。
-t <num> 使用的線程數(默認:4)
-R 每個連接可處理的最大請求數。
-C 禁用CAS。
-b 設置后臺日志隊列的長度(默認:1024)
-B 綁定協議 - 可能值:ascii,binary,auto(默認)
-I 重寫每個數據頁尺寸。調整數據項最大尺寸。
查看詳情
#ps aux|grep mem???
輸出pid
#cat /usr/local/memcached/memcached.pid
?
狀態
#?telnet 127.0.0.1 11211
STAT limit_maxbytes就是最大內存是100M。
增加內存到200M
#?/usr/local/memcached/bin/memcached -d -m 200 -uroot -l 0.0.0.0 -p 11211 -c 512 -P /usr/local/memcached/memcached.pid
先后2次查看內存使用
# top -n 1 |grep Mem
在啟動memcached的時候可以通過-vv來查看slab的種類:
# /usr/local/memcached/bin/memcached -d -m 100 -uroot -l 0.0.0.0 -p 11211 -c 512 -P /usr/local/memcached/memcached.pid -vv
# /usr/local/memcached/bin/memcached -d -m 512 -l 0.0.0.0 -p 11211 -u root -vv
默認一個slab=1048576字節=1024K=1M
默認的truck是48
改為240
# /usr/local/memcached/bin/memcached -d -m 100? -n 240 -uroot -l 0.0.0.0 -p 11211 -c 512 -P /usr/local/memcached/memcached.pid? -vv
# /usr/local/memcached/bin/memcached -d -m 512 -n 240 -l 0.0.0.0 -p 11211 -u root -vv
增長因子f默認是1.25,該值越小所能提供的chunk間隔越小,可以減少內存的浪費
# /usr/local/memcached/bin/memcached -d -m 512? -f 2 -l 0.0.0.0 -p 11211 -u root -vv
修改-I改變每個slab的大小:
第一次最大-I只有2048,然后改為4056
查看slabs狀態
# stats slabs?? 顯示各個slab的信息,包括chunk的大小、數目、使用情況等
# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
# set key1 0 0 3
www
STORED
# get key1
需要注意的是set 最后一個參數就是value字符的長度!
下面是故意構造多個不同chunk的字符存儲效果
# stats
# stats items
調整slab參數
slab對于memcached的空間利用率占有決定因素.
1:比較重要的幾個啟動參數:-f:增長因子,chunk的值會按照增長因子的比例增長(chunk size growth factor).-n:每個chunk的初始大小(minimum space allocated for key+value+flags),chunk大小還包括本身結構體大小.-I:每個slab page大小(Override the size of each slab page. Adjusts max item size)-m:需要分配的大小(max memory to use for items in megabytes)
2:stats slabschunk_size:chunk大小chunk_per_page:每個page的chunk數量total_pages:page數量total_chunks:chunk數量*page數量used_chunks:已被分配的chunk數量free_chunks:曾經被使用,但是目前被回收的chunk數.free_chunks_end:從來沒被使用的chunk數mem_requested:請求存儲的字節數active_slabs:活動的slabs.total_malloced:實際已分配的內存數.
3:重要的結構體和常量typedef struct {
static slabclass_t slabclass[MAX_NUMBER_OF_SLAB_CLASSES];
4:slabs_init函數slabs_init(const size_t limit, const double factor, const bool prealloc)?
unsigned int size = sizeof(item) + settings.chunk_size; ?
#ifndef DONT_PREALLOC_SLABS
5:do_slabs_newslab 初始化slabsdo_slabs_newslab(const unsigned int id) {
//重新分配slabs個數,默認是分配16個頁,后續按照2倍增加static int grow_slab_list (const unsigned int id) {
6:slabs_clsid根據指定大小的數據,確定應該放入到那個桶unsigned int slabs_clsid(const size_t size) {
7:do_slabs_alloc//從class中分配chunk.static void *do_slabs_alloc(const size_t size, unsigned int id) {
#ifdef USE_SYSTEM_MALLOC
工作流程:memcahed實例啟動,根據 -f 和 -n 進行預分配slab。以 -n 為最小值開始,以 -f 為比值生成等比數列,直到1m為止(每個slab的chunk size都要按8的倍數進行補全,比如:如果按比值算是556的話,會再加4到560成為8的整倍數)。然后每個slab分配一個page。當用戶發來存儲請求時(key,value),memcached會計算key+value的大小,看看屬于哪個slab。確定slab后看里面的是否有空閑 chunk放key+value,如果不夠就再向系統申請一個page(如果此時已經達到 -m 參數設置的內存使用上限,則看是否設置了 -M 。如果設置了 -M 則返回錯誤提示,否則按LRU算法刪除數據)。申請后將該page按本slab的chunk size 進行切割,然后分配一個來存放用戶數據。
注意: 1,chunk是在page里面劃分的,而page固定為1m,所以chunk最大不能超過1m。 2,chunk實際占用內存要加48B,因為chunk數據結構本身需要占用48B。 3,如果用戶數據大于1m,則memcached會將其切割,放到多個chunk內。 4,已分配出去的page不能回收。
優化建議 1,-n 參數的設置,注意將此參數設置為1024可以整除的數(還要考慮48B的差值),否則余下來的部分就浪費了。 2,不要存儲超過1m的數據。因為要拆成多個chunk,計算和時間成本都成倍增加。 3,善用stats命令查看memcached狀態。 4,消滅eviction(被刪除的數據)。造成eviction是因為內存不夠,有三個思路:一是在CPU有余力的情況下開啟壓縮(PHP擴展);二是增加內存;三是調整 -f 參數,減少內存浪費。5,調整業務代碼,提高命中率。 6,緩存小數據。省帶寬,省網絡I/O時間,省內存。 7,根據業務特點,為數據尺寸區間小的業務分配專用的memcached實例。這樣可以調小 -f 參數,使數據集中存在少數幾個slab上,內存浪費較少。
Memcached的內存分配以page為單位,默認情況下一個page是1M?,可以通過-I參數在啟動時指定。如果需要申請內存 時,memcached會劃分出一個新的page并分配給需要的slab區域。Memcached并不是將所有大小的數據都放在一起的,而是預先將數據空間劃分為一系列slabs,每個slab只負責一定范圍內的數據存儲,其大小可以通過啟動參數設置增長因子,默認為1.25,即下一個slab的大小是上一個的1.25倍。
Memcached在啟動時通過-m指定最大使用內存,但是這個不會一啟動就占用,是隨著需要逐步分配給各slab的。
?? ? ? ? 如果一個新的緩存數據要被存放,memcached首先選擇一個合適的slab,然后查看該slab是否還有空閑的chunk,如果有則直接存放進去;如 果沒有則要進行申請。slab申請內存時以page為單位,所以在放入第一個數據,無論大小為多少,都會有1M大小的page被分配給該slab。申請到 page后,slab會將這個page的內存按chunk的大小進行切分,這樣就變成了一個chunk的數組,在從這個chunk數組中選擇一個用于存儲 數據。如下圖,slab 1和slab 2都分配了一個page,并按各自的大小切分成chunk數組。
默認情況下memcached把slab分為42類(class1~class42),在class 1中,chunk的大小為96字節,由于一個slab的大小是固定的1048576字節(1M),因此在class1中最多可以有10922個chunk:13107×80 + 16 = 1048576在class1中,剩余的16字節因為不夠一個chunk的大小(80byte),因此會被浪費掉。每類chunk的大小有一定的計算公式的,假定i代表分類,class i的計算公式如下:chunk size(class i) : ?(default_size+item_size)*f^(i-1)+?CHUNK_ALIGN_BYTES
- default_size: 默認大小為48字節,也就是memcached默認的key+value的大小為48字節,可以通過-n參數來調節其大小;
- item_size: item結構體的長度,固定為32字節。default_size大小為48字節,item_size為32,因此class1的chunk大小為48+32=80字節;
- f為factor,是chunk變化大小的因素,默認值為1.25,調節f可以影響chunk的步進大小,在啟動時可以使用-f來指定;
- CHUNK_ALIGN_BYTES是一個修正值,用來保證chunk的大小是某個值的整數倍(在32位機器上要求chunk的大小是4的整數倍)。
?Memcached 采用slab+page+chunk 方式管理內存
–Slab,特定大小的一組chunk
–Page,每次分配給slab的內存空間,會按照slab大小切分為chunk(默認1MB)–Chunk,存儲記錄的內存空間
下面是我畫的memcached的slab結構圖
下面是:http://wenku.baidu.com/view/3e858ff09e314332396893fe.html存儲一個value的大體過程存儲一個value的大體過程
1.先根據要存儲的key、value和flags計算item的大小
item長度=item結構大小 + 鍵長 + 后綴長 + 存儲值長度
2.如果這個item對應的slab還沒有創建,則申請1個page(默認1MB),將這個page按照這個slab類chunk的大寫進行分割,然后將這個 item 存入
3.如果存在,且對應的slab沒用完,存儲
4.如果存在,且對應的slab用完了,則看內存是否用完,用完則啟用LRU,否則申請新的page,存儲
三.調試(帶參數+線程)
在make的時候增加參數:
如果之前已經安裝需要清理,
必須加上編譯選項-O0,不然在gdb內打印變量時提示"<value optimized out>"
# make uninstall
# make CFLAGS="-g -O0"
# make install
在gdb里啟動 # gdb /usr/local/memcached/bin/memcached
給gdb傳參數
帶精靈模式
# set args -d -m 100 -uroot -l 0.0.0.0 -p 11211 -c 512
不帶精靈模式
# set args? -m 100 -uroot -l 0.0.0.0 -p 11211 -c 512
后面都是走正常的調試流程 # r
# break main
# break slabs_init
后面都是走正常的調試流程
# s? 下一步 跟進函數
# n? 下一步 不跟進函數
# c? 下一個斷點
修改變量值?
修改do_daemonize,這樣就不用進入daemon了
#p do_daemonize=0
調試線程
# info threads
顯示進程中所有的線程的概要信息。gdb按順序顯示:
1.線程號(gdb設置)
2.目標系統的線程標識。
3.此線程的當前堆棧。
一前面打*的線程表示是當前線程。
#thread THREADNO
把線程號為THREADNO的線程設為當前線程。命令行參數THREADNO是gdb內定的
線程號。你可以用info threads命令來查看gdb內設置的線程號。gdb顯示該線程
的系統定義的標識號和線程對應的堆棧。比如:
#thread apply [THREADNO] [ALL] ARGS
此命令讓你對一個以上的線程發出相同的命令ARGS,[THREADNO]的含義同上。
如果你要向你進程中的所有的線程發出命令使用[ALL]選項。
無論gdb何時中斷了你的程序(因為一個斷點或是一個信號),它自動選擇信號或
斷點發生的線程為當前線程。gdb將用一個格式為[Switching to SYSTAG]的消息來向你報告。
總結
以上是生活随笔為你收集整理的Memcached安装使用和源码调试的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10月份去甘南有什么好玩的,10月甘南的
- 下一篇: 《Java: The Complete