Memcached是一款開源、高性能、分佈式內存對象緩存系統,可應用各類須要緩存的場景,其主要目的是經過下降對Database的訪問來加速web應用程序。它是一個基於內存的「鍵值對」存儲,用於存儲數據庫調用、API調用或頁面引用結果的直接數據,如字符串、對象等。php
Memcached現已成爲mixi、hatena、Facebook、Vox、LiveJournal等衆多服務中提升Web應用擴展性的重要因素。html
Memcached有以特色
node
1. 簡單key/value存儲:服務器不關心數據自己的意義及結構,只要是可序列化數據便可。存儲項由「鍵、過時時間、可選的標誌及數據」四個部分組成;nginx
2. 功能的實現一半依賴於客戶端,一半基於服務器端:客戶負責發送存儲項至服務器端、從服務端獲取數據以及沒法鏈接至服務器時採用相應的動做;服務端負責接收、存儲數據,並負責數據項的超時過時;web
3. 各服務器間彼此無視:不在服務器間進行數據同步;算法
4. O(1)的執行效率數據庫
5. 清理超期數據:默認狀況下,Memcached工做在Lazy模式下,是一個LRU(最近最少使用)緩存,同時,它按事先預訂的時長清理超期數據;但事實上,memcached不會刪除任何已緩存數據,只是在其過時以後再也不爲客戶所見;並且,memcached也不會真正定期限清理緩存,而僅是當get命令到達時檢查其時長;可是鍵一旦過時,則再次查詢不會返回結果vim
Memcached雖然是一個鍵值存儲server,可是它自己沒法決定緩存那些數據,而是由客戶端決定的鍵名,鍵值,緩存時長,標誌位等後端
Memcached能夠基於文本或者二進制上傳和下載數據瀏覽器
Memcached將全部數據緩存再本身的內存中,並不會進行持久存儲,且它認爲本身也僅僅是一個緩存server,其上的數據丟失並不影響原數據,僅僅對服務有所影響
不一樣的memcached服務器之間不能進行通訊,也不監控對方心跳信息,client端能夠根據調度器如Nginx、haproxy、lvs等基於持久鏈接將數據緩存在多臺memcached上(爲了可以保證始終可以在同一個memcached找到同一個鍵,就須要對鍵作哈希運算,如將鍵作必定運算後/memcached的個數,再取餘,根據餘數將其存儲在固定memcached服務器上,這樣只要知道鍵一計算,就能夠知道它在哪一個server上存着;但這個取餘法有個致命缺陷就是,萬一掛掉或多了一個memcached服務器,其同一個鍵取餘結果就會改變,就不再能根據原來計算方法找到其對應的鍵值,即全部memcached上的緩存都失效)
這時就可使用一致性哈希運算:1到2^32之間取幾個對應區間對應每臺服務器,而後對鍵/2^32取餘,而後根據餘數順時針找最近服務器進行緩存,這樣一旦掛了或加了一個memcached其結果也只讓一臺服務器上的緩存失效
Memcached有兩個很重要組件:
1:buddy system(夥伴系統)爲了保證內存中的空間連續可用buddy system會將臨近的空間碎片合併爲一個大的連續空間,避免了內存碎片的產生
2:slab allocator:當要存儲小於內存頁面大小(4K)數據時如存儲一個128字節的數據,爲了節省空間,slab allocator會將一個4K的內存頁提早劃分爲許多128字節的塊,將其存在裏面,而後標記此塊已近使用,而數據釋放後也不會銷燬這個128字節的塊,會提供給之後的數據存儲使用。而且slab allocator slab爲不一樣大小的數據結構提早準備各類不一樣大小的內存塊,存儲時選擇與它大小最近,且比它大的塊進行存儲,這樣就提升了內存的利用效率
memcached依賴於libevent API,所以要事先安裝之,項目主頁:http://libevent.org/,且memcached是基於Event_Driven(事件驅動)的I/O機制,而event_driven是由libevent這個庫提供的
[root@node1 libevent-2.0.22-stable]# ./configure --prefix=/usr/local/libevent
[root@node1 libevent-2.0.22-stable]# make && make install
[root@node1 local]# echo "/usr/local/libevent/lib/" > /etc/ld.so.conf.d/libevent.conf
[root@node1 local]# ldconfig -v
[root@node1 ~]# yum install -y cyrus-sasl-devel
裝memcached的服務端memcached memcached官網www.memcached,org
[root@node1 tool]# tar memcached-1.4.33.tar.gz
[root@node1 tool]# cd memcached-1.4.33
[root@node1 memcached-1.4.33]# ./configure --enable-sasl --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
[root@node1 memcached-1.4.33]# make && make install
-l <ip_addr>:指定進程監聽的地址;
-d: 以服務模式運行;
-u <username>:以指定的用戶身份運行memcached進程;
-m <num>:用於緩存數據的最大內存空間,單位爲MB,默認爲64MB;
-c <num>:最大支持的併發鏈接數,默認爲1024;
-p <num>: 指定監聽的TCP端口,默認爲11211;
-U <num>:指定監聽的UDP端口,默認爲11211,0表示關閉UDP端口;
-t <threads>:用於處理入站請求的最大線程數,僅在memcached編譯時開啓了支持線程纔有效;
-f <num>:設定Slab Allocator定義預先分配內存空間大小固定的塊時使用的增加因子;
-M:當內存空間不夠使用時返回錯誤信息,而不是按LRU算法利用空間;
-n: 指定最小的slab chunk大小;單位是字節;
-S: 啓用sasl進行用戶認證;
創建一個內存空間大小128M,slab chunk大小從20字節開始、增加因子爲1.2五、以nobody身份運行的memcache緩存空間,且顯示詳細過程
[root@node1 init.d]# /usr/local/memcached/bin/memcached -m 128 -n 20 -f 1.25 -vv -u nobody
slab class 1: chunk size 72 perslab 14563
slab class 2: chunk size 96 perslab 10922
slab class 3: chunk size 120 perslab 8738
slab class 4: chunk size 152 perslab 6898
slab class 5: chunk size 192 perslab 5461
slab class 6: chunk size 240 perslab 4369
slab class 7: chunk size 304 perslab 3449
slab class 8: chunk size 384 perslab 2730
slab class 9: chunk size 480 perslab 2184
slab class 10: chunk size 600 perslab 1747
slab class 11: chunk size 752 perslab 1394
slab class 12: chunk size 944 perslab 1110
slab class 13: chunk size 1184 perslab 885
slab class 14: chunk size 1480 perslab 708
slab class 15: chunk size 1856 perslab 564
slab class 16: chunk size 2320 perslab 451
slab class 17: chunk size 2904 perslab 361
slab class 18: chunk size 3632 perslab 288
slab class 19: chunk size 4544 perslab 230
slab class 20: chunk size 5680 perslab 184
slab class 21: chunk size 7104 perslab 147
slab class 22: chunk size 8880 perslab 118
slab class 23: chunk size 11104 perslab 94
slab class 24: chunk size 13880 perslab 75
slab class 25: chunk size 17352 perslab 60
slab class 26: chunk size 21696 perslab 48
slab class 27: chunk size 27120 perslab 38
slab class 28: chunk size 33904 perslab 30
slab class 29: chunk size 42384 perslab 24
slab class 30: chunk size 52984 perslab 19
slab class 31: chunk size 66232 perslab 15
slab class 32: chunk size 82792 perslab 12
slab class 33: chunk size 103496 perslab 10
slab class 34: chunk size 129376 perslab 8
slab class 35: chunk size 161720 perslab 6
slab class 36: chunk size 202152 perslab 5
slab class 37: chunk size 252696 perslab 4
slab class 38: chunk size 315872 perslab 3
slab class 39: chunk size 394840 perslab 2
slab class 40: chunk size 493552 perslab 2
slab class 41: chunk size 616944 perslab 1
slab class 42: chunk size 771184 perslab 1
slab class 43: chunk size 1048576 perslab 1
從顯示的信息能夠看到slab chunk的最小值系統默認爲72個字節,按1.25倍增加到了1048576大小
[root@node1 init.d]# netstat -tunlp |grep memcached
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 9268/memcached
tcp 0 0 :::11211 :::* LISTEN 9268/memcached
udp 0 0 0.0.0.0:11211 0.0.0.0:* 9268/memcached
udp 0 0 :::11211 :::* 9268/memcached
能夠看到監聽在tcp和udp的11211端口
[root@node1 xinetd.d]# telnet localhost 11211
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stats
STAT pid 9268
STAT uptime 1483
STAT time 1482739946
STAT version 1.4.33
STAT libevent 1.4.13-stable
STAT pointer_size 64
STAT rusage_user 0.209968
STAT rusage_system 1.007846
STAT curr_connections 10
STAT total_connections 12
STAT connection_structures 11
STAT reserved_fds 20
STAT cmd_get 0
STAT crawler_reclaimed 0
STAT crawler_items_checked 0
STAT lrutail_reflocked 0
END
add mykey 0 30 5 ##添加一個鍵,鍵名爲mykey,flag爲0,鍵的有效期爲30秒,大小爲5個字符
hello ##鍵值爲hello
STORED ##顯示已近%STORED
get mykey ##獲取保存的鍵
VALUE mykey 0 5
hello ##鍵值爲hello
END
get mykey
END
##30秒過去後,鍵值失效(雖然memcached爲lazy模型,但過時後就不返回查詢值)
quit
Connection closed by foreign host.
此外memcached還有如下經常使用命令:
replace:僅當鍵已經存在時,replace 命令纔會替換緩存中的鍵。若是緩存中不存在鍵,那麼您將從 memcached 服務器接受到一條 NOT_STORED 響應。
append:將數據追加到當前緩存數據的以後,當緩存數據存在時才存儲。
prepend:將數據追加到當前緩存數據的以前,當緩存數據存在時才存儲
incr: 讓已近存在的鍵自動加一
derc: 讓已近存在的鍵自動減一
get : key 能夠一個或多個,用空格格開
gets:與 get 同樣,但會返回多一個數字,這個數字用來檢查數據是否被修改過,如修改過,這個 數字回改變。
flash_all:清除全部鍵
flash_all 900:在900秒內清空全部鍵
delete: 刪除緩存數據,數據存在返回DELETED,數據不存在返回NOT_FOUND
stats 查看memcached運行狀態
pid Memcached 進程ID
uptime Memcached 運行時間,單位:秒
time Memcached 當前的UNIX時間
version Memcached 的版本號
rusage_user 該進程累計的用戶時間,單位:秒
rusage_system 該進程累計的系統時間,單位:秒
curr_items Memcached 當前存儲的內容數量
total_items Memcached 啓動以來存儲過的內容總數
bytes Memcached 當前存儲內容所佔用的字節數(*/1024/1024=mb)
curr_connections 當前鏈接數量
total_connections Memcached 運行以來接受的鏈接總數
connection_structures Memcached 分配的鏈接結構的數量
cmd_get 查詢請求總數
cmd_set 存儲(添加/更新)請求總數
get_hits 查詢成功獲取數據的總次數
get_misses 查詢成功未獲取到數據的總次數
bytes_read Memcached 從網絡讀取到的總字節數
bytes_written Memcached 向網絡發送的總字節數
limit_maxbytes Memcached 在存儲時被容許使用的字節總數
更詳細的memcached命令請參考下面網友寫的文章
http://blog.csdn.net/fdipzone/article/details/8655681
http://www.cnblogs.com/wayne173/p/5652034.html
如何讓PHP使用memcached?(裝memcached的客戶端)
PHP要結合memcached必須依賴memcached的客戶端庫(也稱爲擴展),對於PHP來講其客戶端庫有兩種,memcache和memcached,其中memcached功能更強大。而對Perl來講其所依賴的客戶端庫爲cache:memcached模塊。
簡單來講memcached爲memcached的服務器端,要讓php在memcached服務器端緩存數據,就必須在在php所在server上裝一個memcached的客戶端(擴展),而這客戶端有兩種,一個叫memcache,另外一個叫memcached(比較高級)
對於C/C++來講其必須依賴libmemcached
下面將演示PHP擴展memcached擴展(要先安裝libmemcached),若是安裝memcache擴展則不用裝libmemcached
若是你要用memcache擴展下載能夠點這個連接http://pecl.php.net/package/memcache
這個連接能夠下載memcached http://pecl.php.net/package/memcached
[root@node1 tool]#wget https://launchpad.net/libmemcached/1.0/1.0.18/+download/libmemcached-1.0.18.tar.gz
[root@node1 tool]# tar -xf libmemcached-1.0.18.tar.gz
[root@node1 tool]# cd libmemcached-1.0.18
[root@node1 libmemcached-1.0.18]# ./configure --prefix=/usr/local/libmemcached --with-memcached
[root@node1 libmemcached-1.0.18]#make && make install
[root@node1 tool]#tar -xf memcached-2.2.0.tgz
[root@node1 tool]#cd memcached-2.2.0
[root@node1 memcached-2.2.0]#/usr/local/php/bin/phpize
[root@node1 memcached-2.2.0]#./configure --with-php-config=/usr/local/php/bin/php-config --enable-memcached --with-libmemcached-dir=/usr/local/libmemcached
[root@node1 memcached-2.2.0]#make && make install
[root@node1 memcached-2.2.0]#vim /etc/php.d/memcache.ini
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/memcached.so
[root@node1 memcached-2.2.0]#service php-fpm restart
啓用Nginx轉發php功能
[root@node1 ~]# vi /etc/nginx/nginx.conf
location ~ \.php$ {
root /web/read;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
}
[root@node1 ~]# service nginx reload
能夠看到memcached擴展已近完成
Nginx結合memcached
[root@node1 ~]# vim /etc/nginx/nginx.conf
server {
listen 80;
server_name www.magedu.com;
location / {
set $memcached_key $uri;#set 鍵名$memcached_key 鍵$uri;
memcached_pass 127.0.0.1:11211; #memcached服務器IP:port
default_type text/html; #默認緩存純文本的內容
error_page 404 @fallback; #若是返回404錯誤(即memcached中沒有相 應的緩存),則轉發給fallback
}
location @fallback {
proxy_pass http://172.16.0.1; #反向代理到後端172.16.0.1處理請求
}
}
配置php將它的會話(session)保存至memcached中
前提:
一、配置各php支持使用memcache;
二、安裝配置好memcached服務器,這裏假設其地址爲172.16.200.11,端口爲11211;
編輯php.ini文件,確保以下兩個參數的值分別以下所示:
[root@node1 ~]# vim /etc/php.ini
session.save_handler = memcache
session.save_path = "tcp://192.168.139.2:11211?persistent=1&weight=1&timeout=1&retry_interval=15"
tcp://172.16.200.11:11211?是你的memcached服務器端的IP:port
?persistent=1 ?傳遞參數,persistent表示持久鏈接
timeout=1 超時時間爲1秒
retry_interval=15 重視時間爲15秒
新建php頁面setsess.php,爲客戶端設置啓用session:
[root@node1 ~]# vim /web/read/setsess.php
<?php
session_start();
if (!isset($_SESSION['www.zxl.com'])) {
$_SESSION['www.zxl.com'] = time();
}
print $_SESSION['www.zxl.com'];
print "<br><br>";
print "Session ID: " . session_id();
?>
新建php頁面showsess.php,獲取當前用戶的會話ID:
[root@node1 ~]# vim /web/read/showsess.php
<?php
session_start();
$memcache_obj = new Memcache;
$memcache_obj->connect('192.168.139.2', 11211);
$mysess=session_id();
var_dump($memcache_obj->get($mysess));
$memcache_obj->close();
?>
而後用瀏覽器分別訪問setsess.php和showsess.php
會看到session信息已近保存在了memcached中
安裝memcached的web界面管理工具memadmin
[root@node1 tool]#tar -xf memadmin-1.0.12.tar.gz
[root@node1 tool]#mv memadmin /web/read/
[root@node1 tool]#cd /web/read/
配置文件以下,能夠修改用戶和密碼
[root@node1 read]# vim memadmin/config.php
<?php
if (!defined('IN_MADM')) exit();
$config['user'] = "admin"; // your username
$config['passwd'] = "admin"; // your password
而後你用瀏覽器就行web界面訪問http://192.18.139.2/memadmin
能夠看到memadmin已近安裝完成
爲編譯安裝的Memcached配置啓動腳本,Memcached SysV的startup腳本代碼以下所示,將其創建爲/etc/init.d/memcached文件:
[root@node1 ~]# vim /etc/init.d/memcached
#!/bin/bash
#
# Init file for memcached
#
# chkconfig: - 86 14
# description: Distributed memory caching daemon
#
# processname: memcached
# config: /etc/sysconfig/memcached
. /etc/rc.d/init.d/functions
## Default variables
PORT="11211"
USER="nobody"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS=""
RETVAL=0
prog="/usr/local/memcached/bin/memcached"
desc="Distributed memory caching"
lockfile="/var/lock/subsys/memcached"
start() {
echo -n $"Starting $desc (memcached): "
daemon $prog -d -p $PORT -u $USER -c $MAXCONN -m $CACHESIZE -o "$OPTIONS"
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch $lockfile
return $RETVAL
}
stop() {
echo -n $"Shutting down $desc (memcached): "
killproc $prog
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f $lockfile
return $RETVAL
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading $desc ($prog): "
killproc $prog -HUP
RETVAL=$?
echo
return $RETVAL
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
restart
;;
condrestart)
[ -e $lockfile ] && restart
RETVAL=$?
;;
reload)
reload
;;
status)
status $prog
RETVAL=$?
;;
*)
echo $"Usage: $0 {start|stop|restart|condrestart|status}"
RETVAL=1
esac
exit $RETVAL
使用以下命令配置memcached成爲系統服務:
[root@node1 ~]# chmod +x /etc/init.d/memcached
[root@node1 ~]# chkconfig --add memcached
[root@node1 ~]# service memcached start
Starting Distributed memory caching (memcached): [ OK ]
本次實驗完成!