3.1 Memcached基础
3.1.1 什么是Memcached
Memcached是一个免费开源的、高性能的、具有分布式内存对象的缓存系统,它通过减轻数据库负载加速动态Web应用。最初版本由LiveJournal的Brad Fitzpatrick在2003年开发完成。目前全世界很多用户都在使用它来构建自己的大负载网站或提高自己的高访问网站的响应速度。Memcache是这个项目的名称,而Memcached是服务器端的主程序文件名。
缓存一般用来保存一些经常存取的对象或数据(例如,浏览器会把经常访问的网页缓存起来),通过缓存来存取对象或数据要比磁盘存取快很多。Memcache是一种内存缓存,把经常存取的对象或数据缓存在内存中,内存中缓存的这些数据通过API的方式被存取,数据就像一张大的HASH表,以key-value对的方式存在。Memcache通过缓存经常被存取的对象或数据,来减轻数据库的压力,提高网站的响应速度,构建速度更快的可扩展的Web应用。图3-1展示了Memcache和数据库协作的流程。
这个流程的具体逻辑如下:
1)检查客户端请求的数据是否在Memcache中存在,如果存在,直接把请求的数据返回,不再对数据进行任何操作。
2)如果请求的数据不在Memcache中,就去查询数据库,把从数据库中获取的数据返回给客户端,同时把数据缓存一份到Memcache中。
3)每次更新数据库(如更新、删除数据库的数据)的同时更新Memcache中的数据,保证Memcache中的数据和数据库中的数据一致。
4)当分配给Memcache内存空间用完之后,会使用LRU(Least Recently Used,最近最少使用)策略加到期失效策略,失效的数据首先被替换掉,然后再替换掉最近未使用的数据。
3.1.2 Memcached的特征
Memcached作为高性能的缓存服务器,具有如下特征:
协议简单。
基于libevent的事件处理。
内置的内存管理方式。
互不通信的Memcached之间具有分布特征。
下面分别进行简单介绍。
1.协议简单
Memcached的协议实现比较简单,使用的是基于文本行的协议,能直接通过telnet在Memcached服务器上存取数据。
2.基于libevent的事件处理
了解libevent的用户都知道,libevent是一套利用C开发的程序库,它将BSD系统的kqueue、Linux系统的epoll等事件处理功能封装成一个接口,确保即使服务器端的连接数增加也能发挥很好的性能。Memcached利用这个库进行异步事件处理。关于这个库的详细内容,有兴趣的读者可以查看相关文档。
3.内置的内存管理方式
Memcached有一套自己管理内存的方式,这套管理方式非常高效,所有的数据都保存在Memcached内置的内存中,当存入的数据占满空间时,使用LRU算法自动删除不使用的缓存,即重用过期数据的内存空间。Memcached是为缓存系统设计的,没有考虑数据的容灾问题,和机器的内存一样,重启机器数据将会丢失。
4.互不通信的Memcached之间具有分布特征
各个Memcached服务器之间互相不通信,都是独立的存取数据,不共享任何信息。通过对客户端的设计,让Memcached具有分布式,能支持海量缓存和大规模应用。
3.1.3 Memcached的安装
Memcached的安装比较简单,这里稍加说明。很多平台支持Memcached,常见的有:Linux、FreeBSD、Solaris、Mac OS X。
也可以将Memcached安装在Windows系统上。这里以CentOS为例进行说明。
1.安装libevent
安装Memcached前需要先安装libevent,首先用wget下载libevent。
[root@web181 ~]# wget -b http://www.monkey.org/~provos/libevent-1.4.13-stable.tar.gz
Continuing in background, pid 8752.
Output will be written to `wget-log'.
[root@web181 ~]# tail -5 wget-log | sed '/^$/d'
450K .......... .......... .......... 100% 139K=8.3s #说明下载完成
2010-09-29 23:20:03 (58.6 KB/s) - `libevent-1.4.13-stable.tar.gz' saved [499603/499603]
下面开始安装。
[root@web181 ~]# tar zxf libevent-1.4.13-stable.tar.gz
[root@web181 ~]# cd libevent-1.4.13-stable
[root@web181 libevent-1.4.13-stable]# ./configure
[root@web181 libevent-1.4.13-stable]# make && make install
CentOS系统也可以通过yum直接安装libevent,不过所安装的版本可能比较低。
2.安装Memcached
安装Memcached的过程如下:
[root@web181 ~]# wget -b http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz
Continuing in background, pid 8659.
Output will be written to `wget-log'.
[root@web181 ~]# tail -5 wget-log | sed '/^$/d'
250K .......... .......... .......... .......... ..... 100% 145K=2.8s
2010-09-29 23:18:03 (105 KB/s) - `memcached-1.4.5.tar.gz' saved [302516/302516]
[root@web181 ~]# tar zxf memcached-1.4.5.tar.gz
[root@web181 memcached-1.4.5]# ./configure
[root@web181 memcached-1.4.5]# make && make install
安装完成后,Memcached的默认目录为/usr/local/bin/memcached。
3.启动Memcached
Memcached启动的过程如下:
[root@web181~]# /usr/local/bin/memcached -m 32m -p 11211 -d -u root -P /var/run/memcached.pid -c 256
这里需要说明的是,启动时可能出现如下错误:
[root@web181~]# /usr/local/bin/memcached -m 32m -p 11211 -d -u root -P /var/run/memcached.pid -c 256 -vv
/usr/local/bin/memcached: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory
找不到libevent-1.4.so.2文件的解决的办法是,把/usr/local/lib加入到/etc/ld.so.conf中,过程如下:
[root@web181 ~]# echo "/usr/local/lib" >> /etc/ld.so.conf
[root@web181 ~]# ldconfig
启动过程中所用选项说明如下:
-p,使用的TCP端口。默认为11 211。
-m,最大内存大小。默认为64MB。
-vv,以very vrebose模式启动,将调试信息和错误输出到控制台。
-d,作为守护进程在后台运行。
-c,最大运行的并发连接数,默认是1024,按照服务器的负载量来设定。
-P,设置保存Memcache的pid文件。
-l,监听的服务器IP地址,如果有多个地址。
-u,运行Memcached的用户,默认不能由root用户启动,所以当前用户为root用户时,需要利用-u参数来指定。
还有很多其他选项,通过/usr/local/bin/memcached –h命令可以显示所有可用选项。其中很多选项能改变Memcached的各种行为,推荐读者阅读相关资料。
4.测试启动是否连接正常
下面通过一个示例简单测试连接是否正常,每个步骤的操作含义均在语句后进行注释。
[root@web181 ~]# telnet localhost 11211
Trying 127.0.0.1...
<30 new auto-negotiating client connection
Connected to localhost.localdomain (127.0.0.1).
Escape character is '^]'.
set test 0 0 10 #向test中存入数据
30: Client using the ascii protocol
<30 set test 0 0 10
test_value #输入的key为test存入的数据
>30 STORED
STORED #返回set结果
get test #获取的数据
<30 get test
>30 sending key test
>30 END
VALUE test 0 10
test_value #取得的key为test中的数据
END
quit
<30 quit
<30 connection closed.
Connection closed by foreign host.
5.关闭Memcached
关闭Memcached的命令如下:
[root@web181 ~]# kill `cat /var/run/memcached.pid`
6.安装Memcache的PHP扩展
1)在http://pecl.php.net/package/memcache 中选择想要下载的Memcache版本。
2)这里以memcache-2.2.5版本为例来安装Memcache的PHP扩展。安装代码如下:
[root@web181 ~]# wget -b http://pecl.php.net/get/memcache-2.2.5.tgz
Continuing in background, pid 20072.
Output will be written to `wget-log'.
[root@web181~]# tail -5 wget-log | sed '/^$/d'
0K .......... .......... .......... ..... 100% 24.9K=1.4s
2010-09-30 13:09:27 (24.9 KB/s) - `memcache-2.2.5.tgz' saved [35981/35981]
[root@web181 ~]# tar zxf memcache-2.2.5.tgz
[root@web181 ~]# cd memcache-2.2.5
[root@web181 memcache-2.2.5]#/usr/local/php/bin/phpize
Configuring for:
PHP Api Version: 20041225
Zend Module Api No: 20060613
Zend Extension Api No: 220060519
[root@web181 memcache-2.2.5]#./configure \
--enable-memcache \
--with-php-config=/usr/local/php/bin/php-config
[root@web181 memcache-2.2.5]# make && make install
3)完成上述安装后会有类似以下的提示:
Installing shared extensions:
/usr/local/php-cgi/lib/php/extensions/no-debug-zts-20060613/
4)修改php.ini文件,把php.ini中的extension_dir =” ./”修改为extension_dir = “/usr/local/php/lib/php/extensions/no-debug-zts-20060613/”。
5)添加如下一行代码来载入Memcache扩展:
extension=memcache.so
7.测试Memcache的PHP扩展是否安装成功
运行下面的PHP代码,如果输出“Hello world!”,就表示环境搭建成功。
<?php
$mem = new Memcache;
$mem->connect(‘127.0.0.1’, 11211);
$mem->set(’test’, ‘Hello world!’, 0, 12);
$val = $mem->get(’test’);
echo $val;
?>
3.1.4 Memcached的简单使用过程
前面已经提到过,许多语言都实现了Memcached的客户端,目前应用最多的是通过Perl、PHP实现对Memcached的操作。这里以Perl的Cache::Memcached为例简要说明使用Memcached的过程。Perl的Cache::Memcached在CPAN上对应的地址为:http://search.cpan.org/dist/CacheMemcached/。
通过Cache::Memcached连接Memcached的示例代码如下:
#!/usr/bin/perl
use Cache::Memcached;
my $key = "test";
my $value = "HelloWorld!";
my $expires = 120;
my $memcached = Cache::Memcached->new({
servers => ["127.0.0.1:11211"],
compress_threshold => 100
});
$memcached->add($key, $value, $expires);
my $return = $memcached->get($key);
print "$return\n";
Cache::Memcached的常用选项如下:
servers,用数组指定连接Memcached服务器的IP地址和端口号。
compress_threshold, 启用数据压缩时使用的值。
namespace,指定添加到键的前缀。
另外,利用Cache::Memcached可以将Perl的复杂数据序列化之后再保存,所以能直接将散列、数组、对象都保存到Memcached的缓存中。
1.向Memcached存数据的方法
向Memcached存数据的方法有set、add和replace,这些方法的使用方式相同。
my $add = $memcached->add( ‘键', ‘值', '过期时间' );
my $replace = $memcached->replace( '键', ‘值', '过期时间' );
my $set = $memcached->set( '键', '值', ‘过期时间' );
向Memcached存数据时可以指定过期时间(秒),若不指定过期时间,Memcached则按照LRU算法保存存入的数据。但这三个方法有一些区别:
set, 无论在什么情况下都保存写入的数据。
add,仅当存储空间中不存在key相同的数据时才保存。
replace,仅当存储空间中存在key相同的数据时才保存。
2.获取数据的方法
可以使用get和get_multi方法来获取数据,使用方法如下:
my $value = $memcached->get(‘键');
my $value = $memcached->get_multi(‘键1', '键2', ‘键3');
如果想一次获取多条数据,可以使用get_multi方法。利用get_multi方法可以非同步地同时取得多个键值,其速度要比循环调用get方法快很多倍。
3.删除数据方法
删除数据可以使用delete方法。
$memcached->delete('键', '阻塞时间(秒)');
第一个参数指定要删除的数据的键,第二个参数指定一个时间值,以禁止使用同样的键保存新数据,这个功能可以防止缓存数据的不完整。但是set 方法忽视该阻塞,会继续保存数据。
4.加一和减一方法
可以把Memcached上某一个特定的键值作为计数器使用。
my $return = $memcached->incr('键');
$memcached->add('键', 0) unless defined $return;
加一和减一都属于原子操作,进行这两个操作时若未对键值设置初始值,则不会自动将初始值赋为0。因此,应当进行错误检查,必要时加入初始化操作。