memcached原理及配置
如果一个网站流量很大,则查询数据库将会耗费大量时间。如果将经常查询的的数据和对象缓存到内存中,则需要查询数据库时,直接返回内存中缓存的数据。这中静态化方式则会高效很多。分布式缓存系统是为了解决数据库服务器和web服务器直接的瓶颈。其中memcached是一个开源、高性能、分布式的内存对象缓存系统。主要通过在内存中缓存数据和对象减轻数据库的负载来加速动态web程序。内存中缓存的数据通
过API的方式被存取,数据就像一张大的HASH表,以键-值对方式存在。
读取
执行读取操作的顺序是从 Web 层获取请求(需要执行一次数据库查询)并检查之前在缓存中存储的查询结果。如果我找到所需的值,则返回它。如果未找到,则执行查询并将结果存储在缓存中,然后再将结果返回给 Web 层。
写入
将数据写入到数据库中时,首先需要执行数据库写入操作,然后将之前缓存的任何受此写入操作影响的结果设定为无效。此过程有助于防止缓存和数据库之间出现数据不一致性。
Memcached采用client/server架构,服务端启动守护进程,等待clent请求到达,采用异步I/O,使用libevenet作为事件通知机制。可以建设多个服务端协同工作,但这些服务端之间并不通信,每个server端对自己的数据进行管理,客户端制定server端IP和端口进行通信。缓存在内存中的数据并不会同步到磁盘上,因此,重启后缓存的数据就会丢失。当缓存数据的总大小达到初始设置值时,就会使用LRU算法删除不用的缓存。
Memcached采用slaballocation机制分配和管理内存,其原理是将内存分割成各种尺寸的块chunk,Chunk就是用来存储key-value数据的最小单位,把尺寸相同的块分成组(slab class) ,每个slab class的大小可以在memcached启动时制定GrowethFactor控制,默认值为1.25。这些内存块不会释放,可重复利用。
可同过以下命令看到slab class生成过程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
#/usr/local/memcached/bin/memcached -d -f 1.25 -n 50 -vvv -u nobody slabclass 1: chunk size 104 perslab 10082 slabclass 2: chunk size 136 perslab 7710 slabclass 3: chunk size 176 perslab 5957 slabclass 4: chunk size 224 perslab 4681 slabclass 5: chunk size 280 perslab 3744 slabclass 6: chunk size 352 perslab 2978 slabclass 7: chunk size 440 perslab 2383 slab class 8: chunk size 552 perslab 1899 slabclass 9: chunk size 696 perslab 1506 slabclass 10: chunk size 872 perslab 1202 slabclass 11: chunk size 1096 perslab 956 slabclass 12: chunk size 1376 perslab 762 slabclass 13: chunk size 1720 perslab 609 slabclass 14: chunk size 2152 perslab 487 slabclass 15: chunk size 2696 perslab 388 slabclass 16: chunk size 3376 perslab 310 slabclass 17: chunk size 4224 perslab 248 slabclass 18: chunk size 5280 perslab 198 slabclass 19: chunk size 6600 perslab 158 slabclass 20: chunk size 8256 perslab 127 slabclass 21: chunk size 10320 perslab 101 slabclass 22: chunk size 12904 perslab 81 slabclass 23: chunk size 16136 perslab 64 slabclass 24: chunk size 20176 perslab 51 slabclass 25: chunk size 25224 perslab 41 slabclass 26: chunk size 31536 perslab 33 slabclass 27: chunk size 39424 perslab 26 slabclass 28: chunk size 49280 perslab 21 slabclass 29: chunk size 61600 perslab 17 slabclass 30: chunk size 77000 perslab 13 slabclass 31: chunk size 96256 perslab 10 slabclass 32: chunk size 120320 perslab 8 slabclass 33: chunk size 150400 perslab 6 slabclass 34: chunk size 188000 perslab 5 slabclass 35: chunk size 235000 perslab 4 slabclass 36: chunk size 293752 perslab 3 slabclass 37: chunk size 367192 perslab 2 slabclass 38: chunk size 458992 perslab 2 slabclass 39: chunk size 573744 perslab 1 slabclass 40: chunk size 717184 perslab 1 slabclass 41: chunk size 1048576 perslab 1 <26server listening (auto-negotiate) <27server listening (auto-negotiate) <28send buffer was 124928, now 268435456 <32send buffer was 124928, now 268435456 <31server listening (udp) <35server listening (udp) <30server listening (udp) <34server listening (udp) <29server listening (udp) <33server listening (udp) <28server listening (udp) <32server listening (udp) |
Memcached
常用选项说明
-l <ip_addr>
:指定进程监听的地址;
-d:
以
daemon
模式运行;
-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
进行用户认证;需要在编译时指定
—enable-sasal
当Memcached接收到客户端发送过来的数据时首先会根据收到数据的大小选择一个最合适的Slab Class,然后通过查询Memcached保存着的该Slab Class内空闲Chunk的列表就可以找到一个可用于存储数据的Chunk。当一条数据库过期或者丢弃时,该记录所占用的Chunk就可以回收,重新添加到空闲列表中。从以上过程我们可以看出Memcached的内存管理制效率高,而且不会造成内存碎片,但是它最大的缺点就是会导致空间浪费。因为每个 Chunk都分配了特定长度的内存空间,所以变长数据无法充分利用这些空间。如图所示,将100个字节的数据缓存到128个字节的Chunk中,剩余的28个字节就浪费掉了。
一、安装libevent
memcached依赖于libevent API,因此要事先安装之,项目主页:http://libevent.org/,读者可自行选择需要的版本下载。本文采用的是目前最新版本的源码包libevent-2.0.21-stable.tar.gz。安装过程:
# tar xf libevent-2.0.21-stable.tar.gz
# cd libevent-2.0.21
# ./configure --prefix=/usr/local/libevent
# make && make install
# echo "/usr/local/libevent/lib" > /etc/ld.so.conf.d/libevent.conf
# ldconfig
二、安装配置memcached
1、安装memcached
# tar xf memcached-1.4.15.tar.gz
# cd memcached-1.4.15
# ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
# make && make install
2、memcached SysV的startup脚本代码如下所示,将其建立为/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=$?
[ $RETVAL -eq 0 ] && success && touch $lockfile || failure
echo
return $RETVAL
}
stop() {
echo -n $"Shutting down $desc (memcached): "
killproc $prog
RETVAL=$?
[ $RETVAL -eq 0 ] && success && rm -f $lockfile || failure
echo
return $RETVAL
}
restart() {
stop
start
}
reload() {
echo -n $"Reloading $desc ($prog): "
killproc $prog -HUP
RETVAL=$?
[ $RETVAL -eq 0 ] && success || failure
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成为系统服务:
# chmod +x /etc/init.d/memcached
# chkconfig --add memcached
# service memcached start
三、基本 memcached 客户机命令
set
添加新的键值对,如果以存在,将会重写
add
当缓存中不存在键时,add
命令才会向缓存中添加一个键值对。如果缓存中已经存在键,则之前的值将仍然保持相同,并且将 获得响应NOT_STORED。
replace
仅当键已经存在时,replace
命令才会替换缓存中的键。如果缓存中不存在键,那么您将从 memcached 服务器接受到 一条 NOT_STORED 响应。
get
命令用于检索与之前添加的键值对相关的值。
gets 同get,但返回的信息要多余get
delete
用于删除 memcached 中的任何现有值。您将使用一个键调用 delete
,如果该键存在于缓存中,则删除该值。如果不存 在,则返回一条 NOT_FOUND 消息。
append 在一个存在的项后增加数据。
prepend 在一个存在的项首增加数据
stats 当前memcached实例信息
flush_all 清理缓存中的所有键值对
stats slabs显示slabs信息,可以获取每个slabs的chunksize长度,从而确定数据到底保存在哪个slab
stats items 显示slab中item数目
修改命令语法:
command <key><flags> <expiration time> <byte>
<value>
key
用于查找缓存值
flags
可以包括键值对的整形参数,客户机使用它存储关于键值对的额外信息
expiration time
缓存中保存键值对的时间,秒为单位,
0
表示永远
bytes
缓存中存储的字节
value
存储的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
# telnet localhost 11211 set xiaobai 0 0 3 123 STORED add xiaobai 0 0 3 123 NOT_STORED get xiaobai VALUE xiaobai 0 3 123 END gets xiaobai VALUE xiaobai 0 3 32 123 END append xiaobai 0 0 3 456 STORED get xiaobai VALUE xiaobai 0 6 123456 END prepend xiaobai 0 0 3 789 STORED get xiaobai VALUE xiaobai 0 9 789123456 END delete xiaobai DELETED get xiaobai END |
四、安装Memcached的PHP扩展
①安装PHP的memcache扩展
# tar xf memcache-2.2.5.tgz
# cd memcache-2.2.5
/usr/local/php/bin/phpize
# ./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-20090626/
②编辑/usr/local/php/lib/php.ini,在“动态模块”相关的位置添加如下一行来载入memcache扩展:
extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20090626/memcache.so
而后对memcached功能进行测试,在网站目录中建立测试页面test.php,添加如下内容:
<?php
$mem = new Memcache;
$mem->connect("127.0.0.1", 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已经能够正常工作。
五、使用libmemcached的客户端工具:
访问memcached的传统方法是使用基于perl语言开发的Cache::memcached模块,这个模块在大多数perl代码中都能良好的工作,但也有着众所周知的性能方面的问题。libMemcached则是基于C语言开发的开源的C/C++代码访问memcached的库文件,同时,它还提供了数个可以远程使用的memcached管理工具,如memcat, memping,memstat,memslap等。
1) 编译安装libmemcached
# tar xf libmemcached-1.0.2.tar.gz
# cd libmemcached-1.0.2
# ./configure
# make && make install
# ldconfig
2) 客户端工具
# memcat --servers=127.0.0.1:11211 mykey
# memping
# memslap
# memstat
六、Nginx整合memcached:
server {
listen 80;
server_name www.magedu.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
set $memcached_key $uri;
memcached_pass 127.0.0.1:11211;
default_type text/html;
error_page 404 @fallback;
}
location @fallback {
proxy_pass http://172.16.0.1;
}
}