Memcached是一款開源、高性能、分佈式內存對象緩存系統,可應用各種需要緩存的場景,其主要目的是通過降低對數據庫的訪問來加速web應用程序。它是一個基於內存的“鍵值對”存儲,用於存儲數據庫調用、API調用或頁面引用結果的直接數據,如字符串、對象等。
一、memcached既不是一個代碼加速器,也不是數據庫中間件。其具有以下特點:
⑴內置內存存儲方式:爲了提高性能,memcached中保存的數據都存儲在memcached內置的內存存儲空間中。重啓memcached,重啓操作系統會導致全部數據消失;
⑵簡單key/value存儲:服務器不關心數據本身的意義及結構,只要是可序列化數據即可。存儲項由“鍵、過期時間、可選的標誌及數據”四個部分組成;
⑶O(1)的執行效率;
⑷基於libevent的事件處理:libevent是個函數庫,它將Linux的epoll、BSD類操作系統的kqueue等時間處理功能封裝成統一的接口。memcached使用這個libevent庫,能發揮高性能;
⑸功能的實現一半依賴於客戶端,一半基於服務器端:客戶負責發送存儲項至服務器端、從服務端獲取數據以及無法連接至服務器時採用相應的動作;服務端負責接收、存儲數據,並設置數據項的過期時長;
⑹各服務器間不會通信以共享信息;memcached雖然是分佈式緩存服務器,但服務器端並沒有分佈式功能,此功能主要通過客戶端實現;
⑺清理超期數據:默認情況下,Memcached是一個LRU緩存,同時,它按事先預訂的時長清理超期數據;但事實上,memcached不會刪除任何已緩存數據,只是在其過期之後不再爲客戶端所見;而且,memcached也不會真正按期限清理緩存,而僅是當get命令到達時檢查其時長,發現過期才清理;
二、memcached的內存管理
可參考http://blog.csdn.net/dato/article/details/1968663
三、安裝memcached
1、memcached依賴於libevent實現併發處理,先要安裝後libevent包,不過此包是系統標配;
yum -y install memcached
2、啓動memcached服務
service memcached start #memcached默認監聽在TCP和UDP的11211號端口
[root@node4 ~]# rpm -q libevent libevent-1.4.13-4.el6.x86_64 [root@node4 ~]# yum -y install memcached ... [root@node4 ~]# rpm -ql memcached /etc/rc.d/init.d/memcached /etc/sysconfig/memcached #主配置文件 /usr/bin/memcached #主程序 /usr/bin/memcached-tool /usr/share/doc/memcached-1.4.4 ... [root@node4 ~]# vim /etc/sysconfig/memcached PORT="11211" USER="memcached" MAXCONN="1024" #併發連接數 CACHESIZE="64" #用於緩存的空間大小 OPTIONS="" [root@node4 ~]# service memcached start ... [root@node4 ~]# ss -tunl Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port udp UNCONN 0 0 :::11211 :::* tcp LISTEN 0 128 :::11211 :::* tcp LISTEN 0 128 *:11211 *:* ...
3、memcached主程序常用選項
-l <ip_addr>:指定進程監聽的地址
-d: 以守護進程模式運行;
-u <username>:以指定的用戶身份運行memcached進程;
-m <num>:用於緩存數據的最大內存空間,單位爲MB,默認爲64MB;
-c <num>:最大支持的併發連接數,默認爲1024;
-p <num>: 指定監聽的TCP端口,默認爲11211;
-P <filename>: pid文件
-U <num>:指定監聽的UDP端口,默認爲11211,0表示關閉UDP端口;
-t <threads>:用於處理入站請求的最大線程數,僅在memcached編譯時開啓了支持線程纔有效;
-f <num>:設定Slab Allocator定義預先分配內存空間大小固定的塊時使用的增長因子;默認爲1.25
-M:當內存空間不夠使用時返回錯誤信息,而不是按LRU算法利用空間;
-n: 指定最小的slab chunk大小;單位是字節;
-S: 啓用sasl進行用戶認證;
[root@node4 ~]# memcached -u memcached -vv 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 ... [root@node4 ~]# memcached-tool 127.0.0.1 # Item_Size Max_age Pages Count Full? Evicted Evict_Time OOM 1 96B 80717s 1 1 no 0 0 0 [root@node4 ~]# memcached-tool 127.0.0.1 stats #127.0.0.1:11211 Field Value ... pointer_size 64 rusage_system 1.216815 rusage_user 1.241811 threads 4 time 1463497553 total_connections 17 total_items 7 uptime 81292 version 1.4.4
四、Memcached提供了爲數不多的幾個命令來完成與服務器端的交互,這些命令基於memcached的協議實現。
1、存儲類命令:set, add, replace, append, prepend
用法:<command> <key> <flag> <expire> <size>
<value>
例如:set user 0 0 8 #過期時長爲0表示永不過期
jerry
set:無論如何都存儲,數據不存在時存儲,數據存在時更新
add:數據不存在時進行添加
replace:替換
append:將數據追加到當前緩存數據的之後
prepend:將數據追加到當前緩存數據的之前
2、獲取數據類命令:get, delete, incr/decr
get key1 key2...:讀取
incr/decr key:對數字型的對象進行增/減操作
3、統計類命令:
stats:查看memcached運行狀態
stats items:
stats slabs:顯示各個slab的信息,包括chunk的大小、數目、使用情況等
stats sizes:輸出所有item的大小和個數
4、清理命令:
delete key:刪除
flush_all:將當前所有緩存數據設置爲過期,但不會釋放內存
[root@node4 ~]# telnet 127.0.0.1 11211 #使用telnet命令測試memcached的使用 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. set user 0 60 5 jerry STORED add gender 0 60 6 female STORED get user VALUE user 0 5 jerry END delete gender DELETED stats STAT pid 37622 STAT uptime 80761 STAT time 1463497022 STAT version 1.4.4 STAT pointer_size 64 STAT rusage_user 1.241811 STAT rusage_system 1.173821 STAT curr_connections 10 STAT total_connections 15 STAT connection_structures 11 ... STAT listen_disabled_num 0 STAT threads 4 STAT conn_yields 0 STAT bytes 74 STAT curr_items 1 STAT total_items 7 STAT evictions 0 END
五、PHP作爲memcached的客戶端
1、在php-fpm服務器上安裝PHP的memcache擴展
# wget https://pecl.php.net/get/memcache-2.2.7.tgz
# tar xf memcache-2.2.7.tgz
# cd memcache-2.2.7
# /usr/local/php/bin/phpize 生成configure文件
# ./configure --with-php-config=/usr/local/php/bin/php-config --enable-memcache
# make && make install
安裝完後會有類似以下的提示:
Installing shared extensions: /usr/local/php/lib/php/extensions/no-debug-non-zts-20130626/
2、編輯/usr/local/php/lib/php.ini,在“動態模塊”相關的位置添加memcache擴展的路徑:
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20130626/memcache.so
◆補充:rpm方式安裝的php-fpm如何加載擴展模塊
此種情況需要先安裝php-devel包,該包能提供phpize和php-config兩個二進制程序。其餘步驟與上述類似,根據實際情況做適當修改即可。
# yum -y install php-devel
......
# ./configure --with-php-config=/usr/bin/php-config --enable-memcache
...
cp tmp-php.ini /etc/php.d/
vim /etc/php.d/tmp-php.ini
extension=/usr/lib64/php/modules/memcache.so
示例:
#此例中的php-fpm是使用rpm方式安裝的,所以若欲對其做擴展就要先安裝php-devel [root@node1 ~]# yum -y install php-devel ... [root@node1 ~]# rpm -ql php-devel /etc/rpm/macros.php /usr/bin/php-config /usr/bin/phpize /usr/include/php ... [root@node1 ~]# wget https://pecl.php.net/get/memcache-2.2.7.tgz #下載memcache擴展源碼包 ... [root@node1 ~]# tar xf memcache-2.2.7.tgz [root@node1 ~]# cd memcache-2.2.7 [root@node1 memcache-2.2.7]# phpize #生成configure文件 Configuring for: PHP Api Version: 20090626 Zend Module Api No: 20090626 Zend Extension Api No: 220090626 [root@node1 memcache-2.2.7]# ls acinclude.m4 config9.m4 config.sub CREDITS Makefile.global memcache.php memcache_standard_hash.c README aclocal.m4 config.guess configure example.php memcache.c memcache_queue.c missing run-tests.php autom4te.cache config.h.in configure.in install-sh memcache_consistent_hash.c memcache_queue.h mkinstalldirs build config.m4 config.w32 ltmain.sh memcache.dsp memcache_session.c php_memcache.h [root@node1 memcache-2.2.7]# ./configure --with-php-config=/usr/bin/php-config --enable-memcache #編譯 ... [root@node1 memcache-2.2.7]# make && make install ... Build complete. Don't forget to run 'make test'. Installing shared extensions: /usr/lib64/php/modules/ #memcache模塊的目錄 [root@node1 memcache-2.2.7]# ls /usr/lib64/php/modules/ curl.so fileinfo.so json.so memcache.so phar.so zip.so [root@node1 memcache-2.2.7]# cp tmp-php.ini /etc/php.d/ [root@node1 memcache-2.2.7]# vim /etc/php.d/tmp-php.ini 在Dynamic Extensions段下添加: extension=/usr/lib64/php/modules/memcache.so [root@node1 memcache-2.2.7]# service php-fpm restart ...
3、對memcached功能進行測試,在網站目錄中建立測試頁面test.php,添加如下內容:
<?php
$mem = new Memcache;
$mem->connect("192.168.30.14", 11211) or die("Could not connect");
$version = $mem->getVersion();
echo "Server's version: ".$version."<br/>\n";
$mem->set('hellokey', 'Hello World', 0, 600) or die("Failed to save data at the memcached server");
echo "Store data in the cache (data will expire in 600 seconds)<br/>\n";
$get_result = $mem->get('hellokey');
echo "$get_result is from memcached server.";
?>
如果有輸出“Hello World is from memcached.”等信息,則表明memcache已經能夠正常工作。
[root@node1 ~]# vim /web/scripts/memtest.php #創建一個測試頁 <?php $mem = new Memcache; $mem->connect("192.168.30.14", 11211) or die("Could not connect"); $version = $mem->getVersion(); echo "Server's version: ".$version."<br/>\n"; $mem->set('hellokey', 'Hello World', 0, 600) or die("Failed to save data at the memcached server"); echo "Store data in the cache (data will expire in 600 seconds)<br/>\n"; $get_result = $mem->get('hellokey'); echo "$get_result is from memcached server."; ?>
六、php程序調用memcached服務的另一個擴展memcached
memcache擴展是原生的(基於pecl擴展庫),而memcached擴展是基於libmemcached庫開發的,libmemcached是memcache的C接口,具有低內存,線程安全等特點;memcached擴展支持Binary Protocol,而memcache擴展不支持;總之,memcached擴展相對來說具有更高的性能。
libmemcached還提供了數個可以遠程使用的memcached管理工具,如memcat, memping,memstat,memslap等。
既然memcached擴展基於limemcached,因此要先編譯安裝libmemcached;libmemcached的源碼包可到https://launchpad.net/libmemcached/+download獲取,memcached擴展的源碼包可到http://pecl.php.net/上獲取;
編譯memcached擴展:
./configure --with-libmemcached-dir=/path/to/somedir(指定libmemcached的安裝目錄) --enable-memcached
其它步驟與安裝memcache擴展類似,不再贅述
七、memcached的圖形管理工具
memcached的圖形管理管理工具主要有memcachephp、memadmin-master、phpMemcachedAdmin;
phpMemcachedAdmin的壓縮包可到http://blog.elijaa.org/phpmemcachedadmin-download-version-1-2-2/獲取
[root@node1 scripts]# ls index.php memcachephp.zip memtest.php [root@node1 scripts]# unzip memcachephp.zip [root@node1 scripts]# ls index.php memcache.php memcachephp.zip memtest.php [root@node1 scripts]# vim memcache.php <?php ... $VERSION='$Id: memcache.php,v 1.1.2.3 2008/08/28 18:07:54 mikl Exp $'; define('ADMIN_USERNAME','magedu'); // Admin Username #設置一個賬號和密碼 define('ADMIN_PASSWORD','123'); // Admin Password define('DATE_FORMAT','Y/m/d H:i:s'); define('GRAPH_SIZE',200); define('MAX_ITEM_DUMP',50); $MEMCACHE_SERVERS[] = '192.168.30.14:11211'; // add more as an array #指定memcached服務器地址 ...
八、memcached的分佈式
memcached本身沒有“分佈式”的功能,memcached的分佈式是由客戶端實現的。memcached的客戶端接口(API,函數庫)用hash算法根據“鍵”來決定保存數據的memcached服務器。獲取數據時把要獲取的“鍵”傳遞給函數庫,函數庫通過與數據保存時相同的算法,根據“鍵”選擇服務器。使用的算法相同,就能選中與保存時相同的服務器。這樣,將不同的鍵保存到不同的服務器上,就實現了memcached的分佈式。memcached服務器增多後,鍵就會分散,即使一臺memcached服務器發生故障無法連接,也不會影響其他的緩存。
爲了減小增刪節點對緩存的影響和增加緩存的平衡性,應儘量使用“一致性hash”算法,關於“一致性hash”算法,可參考http://blog.csdn.net/cywosp/article/details/23397179
1、使用“一致性hash”算法做緩存分佈示例
①啓動若干個memcached服務器;這裏爲演示方便,僅在一個memcached服務主機上啓動幾個實例
[root@node4 ~]# memcached -d -u memcached -m 20 -p 11211 [root@node4 ~]# memcached -d -u memcached -m 20 -p 11212 [root@node4 ~]# memcached -d -u memcached -m 20 -p 11213 [root@node4 ~]# ss -tnl State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 128 :::11211 :::* LISTEN 0 128 *:11211 *:* LISTEN 0 128 :::11212 :::* LISTEN 0 128 *:11212 *:* LISTEN 0 128 :::11213 :::* LISTEN 0 128 *:11213 *:* ...
②修改php的memcache擴展源碼包中的memcache.c文件中的算法設置,然後重新編譯
"memcache.hash_strategy", "consistent"
MEMCACHE_G(hash_strategy) = MMC_CONSISTENT_HASH;
當然,可不用修改源碼重新編譯,還有另外的設置方法,可參考http://wtm-mac.iteye.com/blog/1687746
[root@node1 ~]# tar xf memcache-2.2.7.tgz [root@node1 ~]# cd memcache-2.2.7 [root@node1 memcache-2.2.7]# vim memcache.c ... "memcache.hash_strategy", "consistent" ... MEMCACHE_G(hash_strategy) = MMC_CONSISTENT_HASH; # 之後的編譯安裝的步驟略
③創建一個測試文件
vim /web/scripts/distribute.php
[root@node1 ~]# vim /web/scripts/distribute.php $mem = new Memcache; $mem->addServer('192.168.30.14', 11211); $mem->addServer('192.168.30.14', 11212); $mem->addServer('192.168.30.14', 11213); $key1 = 'mdtest1'; $value1 = '1'; $mem->add($key1, $value1); $key2 = 'mdtest2'; $value2 = '2'; $mem->add($key2, $value2); $key3 = 'mdtest3'; $value3 = '3'; $mem->add($key3, $value3); $key4 = 'mdtest4'; $value4 = '4'; $mem->add($key4, $value4); $key5 = 'mdtest5'; $value5 = '5'; $mem->add($key5, $value5); $key6 = 'mdtest6'; $value6 = '6'; $mem->add($key6, $value6); echo "OK"; ?>
2、利用magent搭建memcached集羣
magent是一個緩存代理服務器,可以連接多臺後端Memcached服務器,它接受客戶端的請求,根據一定的算法做緩存分佈,而且還能對後端memcached緩存做高可用。具體的安裝配置可參考http://www.php-note.com/article/detail/800
九、Nginx整合memcached
nginx的memcached模塊能夠實現調用memcached服務進行緩存
配置示例:
server {
listen 80;
server_name www.magedu.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
set $memcached_key $uri?$args; #表示將請求的URI作爲查詢的key
memcached_pass 127.0.0.1:11211;
default_type text/html;
error_page 404 @fallback;
}
location @fallback {
proxy_pass http://172.16.0.1;
}
}
memcached模塊中的一些指令:
memcached_pass address;
memcached_buffer_size size;
memcached_connect_timeout time;
memcached_read_timeout time;
memcached_send_timeout time;
這些指令與proxy模塊中的指令類似,其用法不再贅述,可查看官方文檔