1 Memcached簡介
1. Memcached是高性能分佈式對象緩存系統,官方主頁http://memcached.org/,主頁上對它的介紹是:爲來自數據庫調用、API調用、或者頁面渲染的結果的小塊任意數據(字符串、對象)的一個內存中的鍵值存儲。
許多Web應用都將數據保存到RDBMS中,應用服務器從中讀取數據並在瀏覽器中顯示。但隨着數據量的增大、訪問的集中,就會出現RDBMS的負擔加重、數據庫響應惡化、網站顯示延遲等重大影響。
這時就該memcached大顯身手了。memcached是高性能的分佈式內存緩存服務器。一般的使用目的是,通過緩存數據庫查詢結果,減少數據庫訪問次數,以提高動態Web應用的速度、提高可擴展性。
2. Memcached的基本工作原理
如下爲memcached的工作流程示意圖,
首次訪問:從RDBMS中取得數據保存在memcached;
第二次後:從memcached中取得數據顯示頁面。類似squid在web網頁緩存中的作用。
3. Memcached的特徵
memcached作爲高速運行的分佈式緩存服務器,具有以下的特點。
協議簡單
memcached的服務器客戶端通信並不使用複雜的XML等格式,而使用簡單的基於文本行的協議。因此,通過telnet也能在memcached上保存數據、取得數據。
基於libevent的事件處理
libevent是個程序庫,它將Linux的epoll、BSD類操作系統的kqueue等事件處理功能封裝成統一的接口。即使對服務器的連接數增加,也能發揮O(1)的性能。memcached使用這個libevent庫,因此能在Linux、BSD、Solaris等操作系統上發揮其高性能。
內置內存存儲方式
爲了提高性能,memcached中保存的數據都存儲在memcached內置的內存存儲空間中。由於數據僅存在於內存中,因此重啓memcached、重啓操作系統會導致全部數據消失。另外,內容容量達到指定值之後,就基於LRU(Least Recently Used)算法自動刪除不使用的緩存。memcached本身是爲緩存而設計的服務器,因此並沒有過多考慮數據的永久性問題。
memcached互不通信的分佈式
memcached儘管是“分佈式”緩存服務器,但服務器端並沒有分佈式功能。各個memcached不會互相通信以共享信息。分佈式的實現取決於客戶端。如下爲memcached分佈式實現示意圖,
4. 緩存與數據庫的同步
比較保險的做法是:查詢的時候(讀)從緩存中取,add、updae、delete的時候(寫)同時操作緩存與DB。
當然你也可以定時同步緩存與DB的數據,不同的業務應該有不同的選擇。
2 Memcached安裝、啓動
2.1 安裝前準備
memcached依賴於libevent庫,在安裝前需保證libevent庫已經安裝
yum install libevent libevent-devel
2.2 安裝
可以從官網下載到最新版本的memcached,直接下載請戳http://www.memcached.org/files/memcached-1.4.17.tar.gz,解壓、編譯安裝:
tar zxvf memcached-1.4.17.tar.gz ; cd memcached-1.4.17
./configure --prefix=/usr/local/memcached
make
make install
2.3 啓動
啓動前防火牆設置:關閉iptables或者添加以下內容到iptables中:
-A INPUT -m state NEW -m tcp -p tcp --dport 11211 -j ACCEPT
-A INPUT -m state NEW -m udp -p udp --dport 11211 -j ACCEPT
/usr/local/memcached/bin/memcached -u root -p 11211 -m 512m -vv
slab class 1: chunk size 80 perslab 13107
slab class 2: chunk size 104 perslab 10082
slab class 3: chunk size 136 perslab 7710
slab class 4: chunk size 176 perslab 5957
slab class 5: chunk size 224 perslab 4681
slab class 6: chunk size 280 perslab 3744
slab class 7: chunk size 352 perslab 2978
slab class 8: chunk size 440 perslab 2383
slab class 9: chunk size 552 perslab 1899
slab class 10: chunk size 696 perslab 1506
slab class 11: chunk size 872 perslab 1202
slab class 12: chunk size 1096 perslab 956
slab class 13: chunk size 1376 perslab 762
slab class 14: chunk size 1720 perslab 609
slab class 15: chunk size 2152 perslab 487
slab class 16: chunk size 2696 perslab 388
slab class 17: chunk size 3376 perslab 310
slab class 18: chunk size 4224 perslab 248
slab class 19: chunk size 5280 perslab 198
slab class 20: chunk size 6600 perslab 158
slab class 21: chunk size 8256 perslab 127
slab class 22: chunk size 10320 perslab 101
slab class 23: chunk size 12904 perslab 81
slab class 24: chunk size 16136 perslab 64
slab class 25: chunk size 20176 perslab 51
slab class 26: chunk size 25224 perslab 41
slab class 27: chunk size 31536 perslab 33
slab class 28: chunk size 39424 perslab 26
slab class 29: chunk size 49280 perslab 21
slab class 30: chunk size 61600 perslab 17
slab class 31: chunk size 77000 perslab 13
slab class 32: chunk size 96256 perslab 10
slab class 33: chunk size 120320 perslab 8
slab class 34: chunk size 150400 perslab 6
slab class 35: chunk size 188000 perslab 5
slab class 36: chunk size 235000 perslab 4
slab class 37: chunk size 293752 perslab 3
slab class 38: chunk size 367192 perslab 2
slab class 39: chunk size 458992 perslab 2
slab class 40: chunk size 573744 perslab 1
slab class 41: chunk size 717184 perslab 1
slab class 42: chunk size 1048576 perslab 1
<26 server listening (auto-negotiate)
<27 server listening (auto-negotiate)
<28 send buffer was 112640, now 268435456
<29 send buffer was 112640, now 268435456
<28 server listening (udp)
<28 server listening (udp)
<28 server listening (udp)
<29 server listening (udp)
<29 server listening (udp)
<29 server listening (udp)
<28 server listening (udp)
<29 server listening (udp)
memcached常用參數說明:
-d:啓動一個守護進程.
-m:分配給Memcache使用的內存數量,單位是MB
-u:運行Memcache的用戶
-l:監聽的服務器IP地址
-p:設置Memcache監聽的端口,默認爲11211
-c:最大運行的併發連接數,默認是1024,可按照服務器的負載量來設定.
-P:設置保存Memcache的pid文件
-vv:詳細的輸出信息顯示
2.4 製作memcached啓動腳本
cat memcached.sh:
#!/bin/bash
# Description: start|stop|restart the Memcached services.
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
. /etc/rc.d/init.d/functions
memcached="/usr/local/bin/memcached"
[ -e $memcached ] || exit 1
start()
{
echo "Start memcached:"
daemon $memcached -d -m 521m -u root -l localhost -p 11211 -c 1500 -P /tmp/memcached.pid
}
stop()
{
echo "Stop memcached:"
#kill -9 `ps aux | grep memcached | awk '{print $2}'`
killproc memcached
}
case "$1" in
start)
start
;;
stop)
stop
;;
restart)
stop
sleep 3
start
;;
*)
echo $"Usage: $0 {start|stop|restart}"
exit 1
esac
exit $?
添加可執行權限:chmod +x memcached.sh
拷貝到/etc/rc.d/init.d/目錄下:cp memcached.sh /etc/rc.d/init.d/memcached
將memcached加入系統啓動項:
chkconfig --level 35 memcached on
啓動memcached:/etc/init.d/memcached start
Start memcached:
[ OK ]
查看memcached是否啓動:ps aux | grep memcached
3 Memcached分佈式集羣實現
由於Memcached本身沒有內置分佈式功能,多個memcached之間互不通信,導致無法實現使用多臺Memcache服務器來存儲不同的數據,最大程度的使用相同的資源;無法同步數據,容易造成單點故障。如果需要實現高可用性,需要通過其他的代理或者客戶端來實現:
3.1 使用magent來實現Memcached集羣
1. magent是一款簡單且有效的memcached服務器代理軟件,項目主頁請戳http://code.google.com/p/memagent/
2. magent的特徵
能夠保持與memcached服務器的連接
支持以下的memcached命令:
get getsdeleteincr decradd set replace prepebd appendcas- 基於libevent庫的事件驅動機制
- 支持ketama算法
- 備份服務器工廠
- unix域socket
3. magent編譯安裝
mkdir magent && cd magent/
wget http://memagent.googlecode.com/files/magent-0.6.tar.gz
tar zxvf magent-0.6.tar.gz
/sbin/ldconfig
sed -i "s#LIBS = -levent#LIBS = -levent -lm#g" Makefile
make
cp magent /usr/bin/magent
cd ../
註解:編譯的時候可能報錯:
gcc -Wall -g -O2 -I/usr/local/include -c -o magent.o magent.c
magent.c: In function ‘writev_list’:
magent.c:729: error: ‘SSIZE_MAX’ undeclared (first use in this function)
magent.c:729: error: (Each undeclared identifier is reported only once
magent.c:729: error: for each function it appears in.)
make: *** [magent.o] Error 1
出錯原因是在Linux系統上,SSIZE_MAX是定義在limits.h文件中,需要加入“#include <limits.h>”到magent.c中
4. magent命令參數說明:
magent 命令參數說明:
-h this message
-u uid
-g gid
-p port, default is 11211. (0 to disable tcp support)
-s ip:port, set memcached server ip and port
-b ip:port, set backup memcached server ip and port
-l ip, local bind ip address, default is 0.0.0.0
-n number, set max connections, default is 4096
-D do not go to background
-k use ketama key allocation algorithm
-f file, unix socket path to listen on. default is off
-i number, max keep alive connections for one memcached server, default is20
-v verbose
5. 集羣實例測試
memcached -m 1 -u root -d -l 127.0.0.1 -p 11211
memcached -m 1 -u root -d -l 127.0.0.1 -p 11212
memcached -m 1 -u root -d -l 127.0.0.1 -p 11213
magent -u root -n 51200 -l 127.0.0.1 -p 12000 -s 127.0.0.1:11211 -s 127.0.0.1:11212 -b 127.0.0.1:11213
註解:
1、分別在11211、11212、11213端口啓動3個Memcached進程,在12000端口開啓magent代理程序;
2、11211、11212端口爲主Memcached,11213端口爲備份Memcached;
3、連接上12000的magent,set key1和set key2,根據哈希算法,key1被寫入11212和11213端口的Memcached,key2被寫入11212和11213端口的Memcached;
4、當11211、11212端口的Memcached死掉,連接到12000端口的magent取數據,數據會從11213端口的Memcached取出;
5、當11211、11212端口的Memcached重啓復活,連接到12000端口,magent會從11211或11212端口的Memcached取數據,由於這兩臺Memcached重啓後無數據,因此magent取得的將是空值,儘管11213端口的Memcached還有數據。可採用定時維護服務器,恢復memcached。
6、memcached和magent可以採用混合的方式來實現分佈式集羣,如下爲模型圖,
6. 測試流程
[root@rango ~]# telnet 127.0.0.1 12000
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
stats
memcached agent v0.4
matrix 1 -> 127.0.0.1:11211, pool size 0
matrix 2 -> 127.0.0.1:11212, pool size 0
END
set key1 0 0 8
rangochen
STORED
set key2 0 0 8
rangochen
STORED
quit
Connection closed by foreign host.
[root@rango ~]# telnet 127.0.0.1 11211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get key1
END
get key2
VALUE key2 0 8
rangochen
END
quit
Connection closed by foreign host.
[root@rango ~]# telnet 127.0.0.1 11212
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get key1
VALUE key1 0 8
rangochen
END
get key2
END
quit
Connection closed by foreign host.
[root@rango ~]# telnet 127.0.0.1 11213
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get key1
VALUE key1 0 8
rangochen
END
get key2
VALUE key2 0 8
rangochen
END
quit
Connection closed by foreign host.
模擬11211、11212端口的Memcached死掉
[root@rango ~]# ps -ef | grep memcached
root 6589 1 0 01:25 ? 00:00:00 memcached -m 1 -u root -d -l 127.0.0.1 -p 11211
root 6591 1 0 01:25 ? 00:00:00 memcached -m 1 -u root -d -l 127.0.0.1 -p 11212
root 6593 1 0 01:25 ? 00:00:00 memcached -m 1 -u root -d -l 127.0.0.1 -p 11213
root 6609 6509 0 01:44 pts/0 00:00:00 grep memcached
[root@rango ~]# kill -9 6589
[root@rango ~]# kill -9 6591
[root@rango ~]# telnet 127.0.0.1 12000
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get key1
VALUE key1 0 8
rangochen
END
get key2
VALUE key2 0 8
rangochen
END
quit
Connection closed by foreign host.
模擬11211、11212端口的Memcached重啓復活
[root@rango ~]# memcached -m 1 -u root -d -l 127.0.0.1 -p 11211
[root@rango ~]# memcached -m 1 -u root -d -l 127.0.0.1 -p 11212
[root@rango ~]# telnet 127.0.0.1 12000
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
get key1
END
get key2
END
quit
Connection closed by foreign host.
3.2 java客戶端
3.2.1 XMemcached是一個基於Java nio的memcached客戶端。它線程安全,結構簡單,支持所有的memcached文本協議和二進制協議,並且有比較優異的性能表現。它還支持一些高級特性,如JMX、動態增刪節點、客戶端統計以及nio連接池等。
3.2.2 與同是基於java nio的spymemcached相比來說,XMemcached具有以下特點:
1)API模型是同步,異步的API使用比較繁瑣,在memcached協議加入noreply後,異步模型的存在價值就更可疑了;
2)支持設置memcached的節點權重;
3)支持動態增刪節點,可以通過編程或者JMX;
4)支持nio連接池,並且允許讓用戶對網絡層面有更多的控制,提供更多的性能優化選項;
5)支持客戶端數據統計;
6)支持Kestrel,Kestrel是一個scala編寫的MQ server。
3.2.3 簡單實例
MemcachedClient client;
try {
client = new XMemcachedClient("localhost",11211);//默認端口
// store a value for one hour(synchronously).
String someObject = "緩存這個一個小時可以嗎?";
client.set("key", 3600, someObject);
// Retrieve a value.(synchronously).
Object getSomeObject = client.get("key");
// delete
client.delete("key");
System.out.println(getSomeObject.toString());
} catch (TimeoutException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (MemcachedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
以上代碼是沒有經過Spring管理的,XMemcachedClient是一個常駐程序。所以可以考慮將它置入到Spring中,配置方式前面已講過。
使用方式見下:
private MemcachedClient memcachedClient;
public void setMemcachedClient(MemcachedClient memcachedClient) {
this.memcachedClient = memcachedClient;
}
注入後直接可使用。
4 Memcached監控
Memcached的監控方式有多種,對應單機和分佈式集羣配置:
4.1 使用memcache.php來監控memcached
這是一種非常方便、快捷的memcached監控方式,下載該文件請戳http://livebookmark.net/memcachephp/memcachephp.zip
下載完後將該文件移動到網頁存放目錄即可,如/var/www/html/(apache)。在使用之前需要設置登錄賬戶、密碼等配置信息:vim memcache.php:
......
define('ADMIN_USERNAME','memcache'); // Admin Username
define('ADMIN_PASSWORD','131415'); // Admin Password
......
$MEMCACHE_SERVERS[] = '192.168.56.1:11211'; // 添加要監控的memcached服務器ip及端口
$MEMCACHE_SERVERS[] = 'mymemcache-server2:11211'; //集羣環境下添加多個ip及端口
登錄http://ip/memcache.php ,查看相應的監控信息。
4.2 使用Nagios的memcached監控插件來實現
1. 可從以下地址下載該插件,請戳 http://cpan.uwinnipeg.ca/cpan/authors/id/Z/ZI/ZIGOROU/Nagios-Plugins-Memcached-0.02.tar.gz
2. 需要保證系統安裝有perl環境:
#rpm -q perl
perl-5.10.1-136.el6.i686
#which perl
/usr/bin/perl
3. 編譯安裝:
#tar zxvf Nagios-Plugins-Memcached-0.02.tar.gz ; cd Nagios-Plugins-Memcached-0.02
#cat README:
......
INSTALLATION
To install this module, run the following commands:
perl Makefile.PL
make
make test
make install
......
#perl Makefile.PL
報錯:Can't locate CPAN.pm in @INC (@INC contains: inc /usr/local/lib/perl5 /usr/local/share/perl5 /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5 /usr/share/perl5 .) at inc/Module/AutoInstall.pm line 635, <STDIN> line 1.
原因是沒有安裝相應的perl的CPAN模塊,解決:yum install perl-CPAN
#make
編譯。會下載一些編譯所需要的文件。
#make install
安裝。從輸出信息中可以知道,默認會將check_memcached安裝到/usr/bin目錄下,將該文件拷貝到Nagios的libexec目錄下:cp /usr/bin/check_memcached /usr/local/nagios/libexec/
測試check_memcached:/usr/local/nagios/libexec/check_memcached -h
報以下錯誤:Base class package "Nagios::Plugin" is empty.
(Perhaps you need to 'use' the module which defines that package first,
or make that module available in @INC (@INC contains: /usr/local/nagios/libexec/../lib /usr/local/lib/perl5 /usr/local/share/perl5 /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5 /usr/share/perl5 .).
at /usr/local/share/perl5/Nagios/Plugins/Memcached.pm line 6
BEGIN failed--compilation aborted at /usr/local/share/perl5/Nagios/Plugins/Memcached.pm line 6.
Compilation failed in require at /usr/local/nagios/libexec/check_memcached line 12.
BEGIN failed--compilation aborted at /usr/local/nagios/libexec/check_memcached line 12.
原因是缺少perl的nagios模塊:yum search perl-nagios
Loading mirror speeds from cached hostfile
* epel: mirrors.hust.edu.cn
* rpmforge: mirrors.neusoft.edu.cn
======================== N/S Matched: perl-nagios =========================
perl-Nagios-NSCA.noarch : Nagios::NSCA Perl module
perl-Nagios-Object.noarch : Nagios::Object - Nagios object configuration
: parsing
perl-Nagios-Plugin.noarch : Family of perl modules to streamline writing
: Nagios
perl-Nagios-Plugin-WWW-Mechanize.noarch : Login to a web page as a user and
: get data as a Nagios plugin
Name and summary matches only, use "search all" for everything.
安裝perl-Nagios-Plugin.noarch:yum install perl-Nagios-Plugin.noarch
再執行測試,報以下錯誤:
Can't locate Carp/Clan.pm in @INC (@INC contains: /usr/local/nagios/libexec/../lib /usr/local/lib/perl5 /usr/local/share/perl5 /usr/lib/perl5/vendor_perl /usr/share/perl5/vendor_perl /usr/lib/perl5 /usr/share/perl5 .) at /usr/local/share/perl5/Nagios/Plugins/Memcached.pm line 8.
BEGIN failed--compilation aborted at /usr/local/share/perl5/Nagios/Plugins/Memcached.pm line 8.
Compilation failed in require at /usr/local/nagios/libexec/check_memcached line 12.
BEGIN failed--compilation aborted at /usr/local/nagios/libexec/check_memcached line 12.
原因是沒有安裝perl的carp:clan包,安裝:yum install perl-Carp-Clan.noarch
最後安裝cache:memcached模塊:yum install perl-Cache-Memcached.noarch
執行:/usr/local/nagios/libexec/check_memcached -h
check_memcached 0.02 [http://search.cpan.org/dist/Nagios-Plugins-Memcached/bin/check_memcache]
This library is free software, you can redistribute it and/or modify
it under the same terms as Perl itself.
Usage: check_memcached [-H host] [-w warnings] [-c critical] [--size-warnng size-warnng] [--size-critical size-critical] [--hit-warning hit-warning] [--hit-critical hit-critical] [-t timeout] [-v] [-h] [-?] [-V] [--extra-opts section@config_file]
......
4. 配置Nagios:
4.1 修改commands.cfg文件,添加監控命令定義:vim /usr/local/nagios/etc/objects/commands.cfg
#check response time(msec) for memcached
define command {
command_name check_memcached_response_11211
command_line /usr/local/bin/check_memcached -H 192.168.56.1 -w 300 -c 500
}
#check cache size ratio(bytes/limit_maxbytes[%]) for memcached
define command {
command_name check_memcached_11211
command_line $USER1$/check_memcached -H 192.168.56.1:11211 --size-warning 80 --size-critical 90
}
#check cache hit ratio(get_hits/cmd_get[%]) for memcached
define command {
command_name check_memcached_hit
command_line /usr/local/bin/check_memcached -H 192.168.56.1 --hit-warning 10 --size-critical 5
}
註解:以上三個命令分別爲:監控memcached是否有響應、監控memcached的內存使用比例 、監控memcached的擊中率。
4.2 添加主機和服務:vim /usr/local/nagios/etc/objects/memcached.cfg
define host{
use linux-server
host_name memcache
alias Memcache_server
address 192.168.56.1
}
define service{
use generic-service
host_name memcache
service_description Memcached_response
check_command check_memcached_response_11211
}
define service{
use generic-service
host_name memcache
service_description Memcached_size
check_command check_memcached_11211
}
define service{
use generic-service
host_name memcache
service_description Memcached_hit
check_command check_memcached_hit
}
4.3 將memcached.cfg添加到Nagios主配置文件中:
cfg_file=/usr/local/nagios/etc/objects/memcached.cfg
4.4 檢查Nagios配置是否有誤:/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg
4.5 重啓Nagios,並登錄Nagios web監控界面查看:
/etc/init.d/nagios restart
4.3 使用MemAdmin監控管理工具來實現
MemAdmin是一款基於 PHP5 & JQuery、 可視化的Memcached管理與監控工具,使用PHP開發,體積小,操作簡單。主頁請戳http://www.junopen.com/memadmin/
主要功能:
服務器參數監控:STATS、SETTINGS、ITEMS、SLABS、SIZES實時刷新
服務器性能監控:GET、DELETE、INCR、DECR、CAS等常用操作命中率實時監控
支持數據遍歷,方便對存儲內容進行監視
支持條件查詢,篩選出滿足條件的KEY或VALUE
數組、JSON等序列化字符反序列顯示
兼容memcache協議的其他服務,如Tokyo Tyrant (遍歷功能除外)
支持服務器連接池,多服務器管理切換方便簡潔
具體配置安裝和使用不再贅述,可自行查看相關文檔,lol
5 總結
本文就Memcached原理、安裝、分佈式安裝和監控等一一較爲詳細的介紹,關於高階的Memcached內部實現原理,還有待研究和學習。
——Rango Chen