Memcached詳解

1.Memcached介紹

Memcached 是一個高性能的分佈式內存對象緩存系統,用於動態Web應用以減輕數據庫負載。它通過在內存中緩存數據和對象來減少讀取數據庫的次數,從而提高動態、數據庫驅動網站的速度。

Memcached基於一個存儲鍵/值對的hashmap。其守護進程(daemon )是用C寫的,但是客戶端可以用任何語言來編寫,並通過memcached協議與守護進程通信

2.Memcached的應用場景

2.1  作爲數據庫的前段緩存應用

1)完整緩存,靜態緩存(易)

例如:商品分類,商品信息,將這些變動較少的(靜態)數據提前存放到內存裏,然後再對外提供服務。用戶訪問只讀取memcached緩存,不讀取數據庫。

 

 

wKioL1f7Gs7h_Mf0AACH1RTKkNc610.png-wh_50


       2)熱點緩存(難)

需要前端程序配合,將熱點數據存放到內存中,用戶訪問這些數據,直接訪問到memcached緩存。第一次訪問非熱點數據時,memcached緩存沒有,就訪問數據庫,獲取數據返回給客戶端,同時在memcached中緩存一份,第二次訪問相同內容時,就不在訪問數據庫,用Memcached緩存直接返回數據。

2.2  作爲集羣的session會話共享存儲

以php的web網站集羣爲例,可以通過修改php.ini

[root@server_02 html]# egrep "session.save" /etc/php.ini|grep -v ";"      
session.save_handler = files
session.save_path = "/var/lib/php/session"

修改結果爲:

session.save_handler = memcache                      --指定通過memcache進行緩存
session.save_path =  "tcp://192.168.1.112:11211"          --memcahced服務器的路徑

2.3  memcached服務器的高可用方案

1) Memcached Repcached

一個單master單 slave的方案,但它的 master/slave都是可讀寫的,而且可以相互同步

2)memagent又名magent

每個magent節點又分別代理多個memcached服務節點,應用系統端使用magent pool來調用memcache進行存儲。通過magent的連接池放的值會分別存在magent代理的所有memcached服務上去。

3)負載均衡器採用一直性哈希,將數據分散在若干個memcached服務器上

 

3.Memcached在業務中的工作流程

wKiom1f7Gynz60reAAbtT_mB77k758.png-wh_50 

4.Memcached服務分佈式集羣實現方法

特殊說明:Memcached的調度算法一般用一致性hash,提高緩存命中率,每臺Memcached都是一部分數據

1.程序端實現

程序加載所有的memcached服務器,通過對key進行hash(一致性哈希)存放緩存。

2.負載均衡器實現

通過對key進行hash(一致性哈希)存放緩存

注:一致性hash不但可以保證每個對象只請求對應唯一的memcahced服務器,而且保證單臺緩存服務器宕機,更新的緩存數據最少

5.Memcached服務特點及工作原理

wKioL1f7Gz2SjV7AAAPGdprgQ6s535.png-wh_50 

1.完全基於內存

2.節點之間相互獨立

3.異步I/O模型,基於libevent模型的事件通知機制

4.緩存數據以key/value鍵值對形式存放

5.C/S模式架構,C語言編寫,總共代碼2000多行

6.數據存放在內存中,斷電會丟失數據

7.緩存空間存放滿之後,採用LRU算法刪除過期緩存數據

 

6.Memcached內存管理機制

6.1 基本概念

1、slab class

在memcached中,對元素的管理是以slab爲單元進行管理的。每個slab class對應一個或多個空間大小相同的chunk。參考下圖一。

2、chunk

存放元素的最小單元。用戶數據item(key、value等)最終會保存在chunk中。memcached會根據元素大小將其放到合適的slab class中。每一個slab class中的chunk空間大小是一樣的,所以元素存放進來後,chunk可能會有部分空間剩餘。參考下圖二、下圖三。

3、page

大小固定爲1MB。當slab class空間不足時,就會申請page,並將page按chunk的大小進行切割。

wKioL1f7G1XDCNBPAACJ68TbOIw503.jpg-wh_50

圖一  slab class邏輯結構圖

wKiom1f7G2bSKaGHAABIq06VNds372.jpg-wh_50

圖二  元素存入memcached會尋找最合適的slab class

wKiom1f7G56hO_GXAAAwbG25-DE383.jpg

圖三 元素放入chunk時可能會有空間浪費

memcached使用自己的內存管理機制,可以有效避免系統內存碎片,避免給操作系統帶來負擔。

6.2 Memcached內存分配方式

啓動memcached時,以-m指定大小的內存將會用於數據的存放。默認情況下,這些內存會被分隔成1M的page。每個page在必要時分配給slab class,然後根據slab class裏chunk的大小,將page分隔成chunk。

一個page被賦給一個slab class後,它將不會再被移動。因爲內存空間有限,如果在slab class 3中使用了較多的page,那麼在slab class 4中就只能使用較少的page。可以這麼認爲,memcached是一個有很多更小的相互獨立的緩存系統,每一個更小的緩存系統實際上就是slab class。每個slab class都有它自己的統計信息以及自己的LRU。

在啓動memcached時,指定-vv參數,可以在啓動日誌中查看每個slab class的chunk大小。

[root@server_01 ~]# memcached  -vv -u root
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

在slab class 1中,每個chunk大小爲96字節,每個頁面包含10922chunk(或item)。這兩個數相乘,應該最近接1個page的大小(默認是1MB)。

當存儲元素時,它們將被放到最合適的slab class中。例如,50字節的元素(包含key、value等信息)將被存放到slab class 1中的chunk,根據之前的說明,此chunk中將會有30字節的空間浪費。如果存放數據總共有90字節,將被存放到slab class 2中,此時會有14字節的空間浪費。

6.3 Memcached優化

Memcached啓動時,通過設置參數-f,可以設置每個slab class下chunk的空間增長率。儘量使每個chunk的size接近具體業務的size,減少內存空間浪費,提高內存利用率

6.4 Memcached內存回收

與redis不同的是,memcached不會主動回收內存。memcached會重複使用失效數據的內存。

如果獲取了一個已失效的數據,memcached將會釋放內存。後續再將新的數據存放進來時,將會重用此內存。

根據LRU(最近最少使用)算法,元素將被踢出以讓給新的元素,或發現有過期的元素,它們的內存將被重用。如果元素還沒有失效(失效日期爲0或者將會在將來失效),slab class已經用完了所有空閒的chunk,並且沒有空閒的page可以分配給此slab class,此時將會執行LRU算法踢出數據

6.5 LRU算法

當存放新的元素時,內存也可能會被回收。如果在相應的slab class裏,既沒有空閒的chunk,也沒有空閒的page,memcached將會使用LRU算法查找應該被回收的元素。它將會查找LRU列表中尾部(最近最少使用)的一些元素,看它們是否已經失效,如果存在失效的元素,則將此元素佔用的空間重用。如果找不到失效的元素,那麼將踢出最尾部還沒有失效的元素。

 

7.Memcached安裝配置

1)安裝libevent(前提)

yum install libevent libevent-devle -y

也可以通過編譯安裝libevent包

2)安裝Memcached服務端

說明:Memcached是服務端

      Memcache是客戶端

[root@server tools]# wget http://memcached.org/files/memcached-1.4.31.tar.gz
[root@server_02 tools]# tar xf memcached-1.4.31.tar.gz 
[root@server_02 tools]# cd memcached-1.4.31
[root@server_02 memcached-1.4.31]# ./configure 
[root@server_02 memcached-1.4.31]# make && make install

3)啓動memcached服務

[root@server_02 memcached-1.4.31]# memcached -d -m 10m -u root -l 192.168.1.112 -p 11211-c 256 -P /tmp/memcached.pid
[root@server_02 memcached-1.4.31]# ss -lntup|grep memcached
udp    UNCONN     0      0          192.168.1.112:11211                *:*      users:(("memcached",833,27),("memcached",833,28),("memcached",833,29),("memcached",833,30))
tcp    LISTEN     0      128        192.168.1.112:11211                 *:*      users:(("memcached",833,26))
[root@server_02 memcached-1.4.31]#

 

-d選項是以一個守護進程啓動,
-m是分配給Memcache使用的內存數量,單位是MB,我這裏是10MB
-u是運行Memcache的用戶,我這裏是root
-l是監聽的服務器IP地址,如果有多個地址的話,我這裏指定了服務器的IP地址192.168.1.112
-p是設置Memcache監聽的端口,最好是1024以上的端口,默認是11211
-c選項是最大運行的併發連接數,默認是1024,我這裏設置了256,按照你服務器的負載量來設定,
-P是設置保存Memcachepid文件,我這裏是保存在 /tmp/memcached.pid

注意:可以通過更改端口號,實現啓動多個memcached實例

4)關閉memcached服務

   1.pkill memcached

   2.kill  `cat /tmp/memcached.pid`

5) memcached存儲數據測試(nc/telnet測試)

[root@server_02 memcached-1.4.31]# telnet 192.168.1.112 11211
Trying 192.168.1.112...
Connected to 192.168.1.112.
Escape character is '^]'.
set key key2 0 0 4
CLIENT_ERROR bad command line format
 
set key1 0 60 4
youd
STORED
get key1
VALUE key1 0 4
youd
END
delete key1
DELETED
get key1
END

命令說明:

<command name> <key> <flags> <exptime> <bytes>\r\n <data block>\r\n
a) <command name> 可以是”setaddreplace
set”表示按照相應的<key>存儲該數據,沒有的時候增加,有的覆蓋。
add”表示按照相應的<key>添加該數據,但是如果該<key>已經存在則會操作失敗。
replace”表示按照相應的<key>替換數據,但是如果該<key>不存在則操作失敗

b) <key> 客戶端需要保存數據的key

c) <flags> 是一個16位的無符號的整數(以十進制的方式表示)
該標誌將和需要存儲的數據一起存儲,並在客戶端get數據時返回。
客戶可以將此標誌用做特殊用途,此標誌對服務器來說是不透明的。

d) <exptime> 過期的時間。
若爲0表示存儲的數據永遠不過時(但可被服務器算法:LRU 等替換)
如果非0(unix時間或者距離此時的秒數),當過期後,服務器可以保證用戶得不到該數據(以服務器時間爲標準)

e) <bytes> 需要存儲的字節數(不包含最後的”\r\n),當用戶希望存儲空數據時,<bytes>可以爲0

f) 最後客戶端需要加上”\r\n”作爲”命令頭”的結束標誌。
<data block>\r\n

緊接着”命令頭”結束之後就要發送數據塊(即希望存儲的數據內容),最後加上”\r\n”作爲此次通訊的結束。

linux nc命令操作memcache方法實例
1)存儲數據:printf “set key 0 10 6\r\nresult\r\n” |nc 192.168.1.112 11211
2)獲取數據:printf “get key\r\n” |nc 192.168.1.112 11211
3)刪除數據:printf “delete key\r\n” |nc 192.168.1.112 11211
4)查看狀態:printf “stats\r\n” |nc 192.168.1.112 11211
5)模擬top命令查看狀態:watch “echo stats” |nc 192.168.1.112 11211

6)清空緩存:printf “flush_all\r\n” |nc 192.168.1.112 11211 (小心操作,清空了緩存就沒了

 

6)php安裝memcache客戶端(擴展memcache模塊)

參考:http://php.net/manual/zh/memcache.installation.php

tar xf memcache-3.0.6.tgz 
cd memcache-3.0.6
phpize
./configure --enable-memcache --with-php-config=/usr/bin/php-config --with-zlib-dir
make && make install

安裝成功後,修改php.ini文件的一下兩項內容:

[root@server_02 html]# egrep "memcache.so|extension" /etc/php.ini|grep -v ";"

extension_dir = "/usr/lib64/php/modules/"         ---擴展模塊的目錄

extension = memcache.so                         - --擴展的模塊名稱

 

用phpinfo查看下memcache是否加載成功

wKiom1f7G-3R37YFAABGT0H79Ck903.png-wh_50 

7)php程序測試memcached

php測試頁面代碼:

[root@server_02 html]# vim memcache.php
<?php
$memcache = new Memcache;
$memcache->connect('192.168.1.112', 11211);
$memcache->set('test', 'successs'); 
echo $memcache->get('test');      
?>

將以上代碼,放到memcache.php文件中,將memcache.php文件放到web服務目錄下/var/www/html

php頁面顯示內容:

wKioL1f7HAWSOqKUAAAg8reVlU8752.png-wh_50 

 

 

 

8.memcached服務的web管理工具memadmin

wget http://www.junopen.com/memadmin/memadmin-1.0.12.tar.gz
tar xf memadmin-1.0.12.tar.gz
mv ./memadmin /var/www/html/memadmin   --將memadmin目錄移動到web服務器目錄下

memadmin默認賬號密碼都是:admin

memadmin網頁效果圖:

wKiom1f7HCSSwWfKAACCqzXrFPg438.png-wh_50 

常見問題:

1.如果啓動Memcached服務的時候遇到了

/usr/local/bin/memcached: error while loading shared libraries: libevent-1.2.so.1: cannot open shared object file: No such file or directory;

解決方案:

[root@localhost bin]# LD_DEBUG=libs memcached -v 
[root@localhost bin]# ln -s /usr/lib/libevent-1.2.so.1 /usr/lib64/libevent-1.2.so.1
[root@localhost bin]# /usr/local/bin/memcached -d -m 100 -u root -p 11211 -c 1000 -P /tmp/memcached.pid
[root@localhost bin]# ps -aux

可以看到啓動的Memcached服務了.

 

2.Memcached服務加載到Linux的啓動項中.萬一機器斷電系統重啓.那麼Memcached就會自動啓動了.

假如啓動Memcache的服務器端的命令爲:
# /usr/local/bin/memcached -d -m 10 -u root -l 192.168.1.112 -p 11211 -c 256 -P /tmp/memcached.pid容來自17jquery

想開機自動啓動的話,只需在/etc/rc.d/rc.local中加入一行,下面命令
/usr/local/memcached/bin/memcached -d -m 10 -p 12000 -u apache -c 256 
上面有些東西可以參考一下:即,ip不指定時,默認是本機,用戶:最好選擇是:apache 或 deamon


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章