- 论坛徽章:
- 0
|
仙子注:
这篇文档是偶很早前写的,并且偶一直也在用memcached.现把它贴出来大家共享下.
memcached,主页在http://www.danga.com/memcached/,是一项开源技术。
memcached是用C写的一个daemon程序,在Linux下支持epoll。运行方法很简单:
./memcached -d -m 1024 -l 192.168.1.102 -p 7789
./memcached -d -m 1024 -l 192.168.1.102 -p 7790
这表示在同一机器上运行2个memcached,每个使用1G内存,一个侦听在7789端口,一个侦听在7790端口。这样可以实现负载均衡,并且一个daemon down掉了,数据会继续在另一个daemon里读写。而真正分布式的应用体现在多主机,多daemon上,就是说完全可以这样运行:
./memcached -d -m 1024 -l 1.1.1.1 -p 1111
./memcached -d -m 1024 -l 1.1.1.1 -p 2222
./memcached -d -m 1024 -l 2.2.2.2 -p 1111
./memcached -d -m 1024 -l 2.2.2.2 -p 2222
....
直到无穷。
这样可以实现高效的负载均衡。在web主机上,通常web进程(如Apache)是CPU敏感,内存不那么敏感的。而memcached典型的是耗内存不耗CPU。因此可将memcached直接跑在前台web主机上,作为数据缓存(或数据库连接池)使用,也就是在web程序与数据库之间多加了一层。
memcached的通信协议是透明的,完全可以根据文档写出自己的API。当然已有现成的Perl和C API。测试了下Perl API,非常容易实现数据的cache,并且性能很好。用这个memcached既可以实现Mysql的连接缓冲池,又可以代替DB_File作为本地数据Cache。
写了个测试脚本如下:
- #!/usr/bin/perl
- use strict;
- use Data::Dumper;
- use DBI;
- use Cache::Memcached;
-
- my $host='192.168.1.101';
- my $dbuser='xxx';
- my $dbpasswd='***';
- my $db='mydb';
-
- my $dsn="dbi:mysql:$db:$host";
- my $dbh=DBI->connect($dsn,$dbuser,$dbpasswd,{PrintError => 1,RaiseError => 0});
- my $test_id=423147;
-
- my $memd = new Cache::Memcached {
- 'servers' => [ "192.168.1.102:7789", "192.168.1.102:7790" ],
- 'debug' => 0,
- 'compress_threshold' => 10_000,
- };
-
- my $val;
- $val = init_object($test_id);
- print Dumper $val;
-
- repl_object($test_id);
- $val = get_object($test_id);
- print Dumper $val;
-
- $val = incr_object($test_id);
- print Dumper $val;
- $val = incr_object($test_id);
- print Dumper $val;
-
- if (del_object($test_id)){
- my $val = get_object($test_id);
- print Dumper $val;
- }
-
- print Dumper $memd->stats('misc');
- $memd->disconnect_all;
-
- #----------------
- # test subroutines
- #
-
- sub init_object {
- my $foo_id = shift;
- my $obj = $memd->get("foo:$foo_id");
- return $obj if $obj;
-
- my $query="select mailfrom,sendtime,subject from rcpt where id=$foo_id";
- $obj = $dbh->selectrow_hashref($query);
- $memd->set("foo:$foo_id", $obj);
- return $obj;
- }
-
- sub get_object {
- my $foo_id = shift;
- my $obj = $memd->get("foo:$foo_id");
- return $obj;
- }
-
- sub del_object {
- my $foo_id = shift;
- $memd->delete("foo:$foo_id");
- }
-
- sub repl_object {
- my $foo_id = shift;
- my $query="select mailfrom,sendtime,subject from rcpt where id=423148";
- my $obj = $dbh->selectrow_hashref($query);
-
- $memd->replace("foo:$foo_id", $obj);
- }
-
- sub incr_object {
- my $foo_id = shift;
- $memd->incr("foo:$foo_id");
- }
复制代码
可以看到关键是此处陈述:
- my $memd = new Cache::Memcached {
- 'servers' => [ "192.168.1.102:7789", "192.168.1.102:7790" ],
- 'debug' => 0,
- 'compress_threshold' => 10_000,
- };
复制代码
这里定义了所有memcached的地址和端口列表。应用程序根据key将数据存放到对应的memcached上。当然数据不是随机存放的,否则查找会很低效。应该是不同的key到不同的daemon之间有个映射算法,这样数据在存取完后可快速访问到,而不是要遍历所有的daemon才能找到.
当然这个API里也定义了很多操作memcached数据的方法,包括增加、删除、更新、替换等,非常灵活。具体的Perl-API接口可见CPAN上Cache::Memcached的POD文档。
网上的测试表明,该技术强于当前的共享内存以及Mysql Cache,Mysql Duplicate技术。livejournal的2K万用户访问量,就是用它来提速的。Slashdot站点也采用了该技术。 |
|