memcached原理和实践


 1.memcached简介
memcached是以LiveJournal旗下Danga Interactive公司的Brad Fitzpatric为首开发的一款软件。现在已成为mixi、hatena、Facebook、Vox、LiveJournal等众多服务中提高Web应用扩展性的重要因素。许多Web应用都将数据保存到RDBMS中,应用服务器从中读取数据并在浏览器中显示。但随着数据量的增大、访问的集中,就会出现RDBMS的负担加重、数据库响应恶化、网站显示延迟等重大影响。这时就该memcached大显身手了。memcached是高性能的分布式内存缓存服务器。一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。

\

2.memcached的特征
memcached作为高速运行的分布式缓存服务器,具有以下的特点:
1)协议简单:memcached的服务器客户端通信并不使用复杂的XML等格式,而使用简单的基于文本行的协议。因此,通过telnet也能在memcached上保存数据、取得数据。
2)基于libevent的事件处理:libevent是个程序库,它将Linux的epoll、BSD类操作系统的kqueue等事件处理功能封装成统一的接口。即使对服务器的连接数增加,也能发挥O(1)的性能。memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能。
3)内置内存存储方式:为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。由于数据仅存在于内存中,因此重启memcached、重启操作系统会导致全部数据消失。另外,内容容量达到指定值之后,就基于LRU(Least Recently Used)算法自动删除不使用的缓存。memcached本身是为缓存而设计的服务器,因此并没有过多考虑数据的永久性问题。
4)memcached不互相通信的分布式:memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息。那么,分布式是完全取决于客户端的实现。
——————————————————————————————————————————
3.Slab Allocation机制:整理内存以便重复使用
目前memcached采用Slab Allocator的机制分配、管理内存。Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块,以完全解决内存碎片问题。

\

1)如上图所示,Slab Allocation将分配的内存分割成各种尺寸的块(chunk,用于缓存记录的内存空间),并把尺寸相同的块分成组(chunk的集合,每个chunk的大小相同)。默认一个slab(chunks)的大小是1MB,叫1Page。
2)slab allocator有重复使用已分配的内存的目的。也就是说,分配到的内存不会释放,而是重复利用。
3)memcached根据收到的数据的大小,选择最适合数据大小的slab。 memcached中保存着slab内空闲chunk的列表,根据该列表选择chunk, 然后将数据缓存于其中。如当来了100bytes数据,会选择最合适的112bytes的chunk(假如slab classes中chunk的大小包含有88bytes、112bytes、144bytes……)
4)Slab Allocator解决了当初的内存碎片问题,但由于分配的是特定长度的内存,因此无法有效利用分配的内存。例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了。
——————————————————————————————————————————
4.memcached的删除机制
1)memcached是缓存,所以数据不会永久保存在服务器上,其实数据不会真正从memcached中消失。实际上memcached不会释放已分配的内存,记录超时后,客户端就无法再看见该记录,其存储空间即可重复使用。
2)Lazy Expiration:memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。因此,memcached不会在过期监视上耗费CPU时间。
3)memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为 Least Recently Used(LRU)机制来分配空间。 顾名思义,这是删除“最近最少使用”的记录的机制。因此,当memcached的内存空间不足时(无法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。
——————————————————————————————————————————
5.memcached的分布式
1)memcached但服务器端并没有“分布式”功能。分布式是完全由客户端程序库实现的。这种分布式是memcached的最大特点。
2)set(存数据到memcached)时,set(‘key’,data),将’key’传给客户端程序库后,客户端实现的算法就会根据“键”来决定保存数据的memcached服务器。服务器选定后,即命令它保存(’key’,data);
3)get(从memcached取数据)时,get(‘key’),此时客户端把’key’传递给函数库,函数库通过与数据保存时相同的算法,根据“键”选择服务器。使用的算法相同,就能选中与保存时相同的服务器,然后发送get命令。只要数据没有因为某些原因被删除,就能获得保存的值。
4)以上将不同的键保存到不同的服务器上,就实现了memcached的分布式。 memcached服务器增多后,键就会分散,即使一台memcached服务器发生故障无法连接,也不会影响其他的缓存,系统依然能继续运行。
5)Cache::Memcached的分布式算法简单来说,就是“根据服务器台数的余数进行分散”。 求得键的整数哈希值[使用crc32函数,如crc32($key)],再除以服务器台数,根据其余数来选择服务器。余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点。那就是当添加或移除服务器时,缓存重组的代价相当巨大。
参考文档:http://tech.idv2.com/2008/07/10/memcached-001/
实践篇
1.memcached的安装
1)memcached是基于libevent的事件处理,所以安装memcached时先要安装libevent库。
yum -y install libevent libevent-devel
2)memcached编译安装比较简单,一般都采用编译安装的方式如下:
wget http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz
tar -zxvf memcached-1.4.5.tar.gz
cd  memcached-1.4.5
./configure
make && make install
——————————————————————————————————————————
2.memcached启动
1)memcached常用参数:(/usr/local/bin/memcached -h)
-p <num>      TCP port number to listen on (default: 11211)
-U <num>      UDP port number to listen on (default: 11211, 0 is off)
-l <ip_addr>  interface to listen on (default: INADDR_ANY, all addresses)
-d            run as a daemon
-u <username> assume identity of <username> (only when run as root)
-m <num>      max memory to use for items in megabytes (default: 64 MB)
-c <num>      max simultaneous connections (default: 1024)
-P <file>     save PID in <file>, only used with -d option
-f <factor>   chunk size growth factor (default: 1.25)
2)以daemon的方式启动memcached
/usr/local/bin/memcached -u nobody -p 11211 -m 64 -c 128 -d
——————————————————————————————————————————
3.memcached结合mysql、perl的实践
cat memcached_mysql.pl
#!/usr/bin/perl
#Usage: test memcahed with mysql and perl
#Made by yunhaozou@gmail.com,2010/12/20
#
use Cache::Memcached;
use DBI;
use Data::Dumper;
use Digest::MD5 qw(md5_hex);
use strict;
#
my $host = “127.0.0.1″;  #db相关信息
my $port = “3306″;
my $db = “zichan_db”;
my $user = “root”;
my $password = “”;
my $dsn = “dbi:mysql:database=$db:hostname=$host:port=$port”;
my $dbh = DBI->connect($dsn,$user,$password) or die “Couldn’t connect to database: ” . DBI->errstr;  #连接db
my $memcached = Cache::Memcached->new({ servers=>["127.0.0.1:11211"],compress_threshold=>10_000});   #连接memcached
#$memcached = Cache::Memcached->new({ servers=>["127.0.0.1:11211","192.168.2.1:11211"],compress_threshold=>10_000}); #表示连接两台机的memcached,这样可以实现负载均衡,一个机器挂了,另一个可以继续用
my $zcsql = “select sn,model,cab_no,func,intra_ip,man_addr,contact from equipment where sn=’0917QAR012′;”;
#
my $result = query_result($zcsql);
print Dumper $result;
$dbh->disconnect();
#
sub query_result{
my $query_sql = shift;
my $query_key = md5_hex($query_sql);  #把查询sql语句转换为MD5值的key
my $que

相关内容

    暂无相关文章