1. 如果你安装了PHP的memcache模块,则使用phpinfo()函数可以看到如下信息
memcache support | enabled |
---|---|
Active persistent connections | 10 |
Revision | $Revision: 1.62 $ |
Directive | Local Value | Master Value |
---|---|---|
memcache.allow_failover | 1 | 1 |
memcache.chunk_size | 8192 | 8192 |
memcache.default_port | 11211 | 11211 |
memcache.max_failover_attempts | 20 | 20 |
其中:Active persistent connections 代表是的已建立的长连接的个数; 注意,该值是当前进程的,因为长连接在进程间是无法共享的。
2. php.ini 中配置解释
[Memcache]
; 一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,
; 它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。
; 是否在遇到错误时透明地向其他服务器进行故障转移。
memcache.allow_failover = On
; 接受和发送数据时最多尝试多少个服务器,只在打开memcache.allow_failover时有效。memcache.max_failover_attempts = 20
; 数据将按照此值设定的块大小进行转移。此值越小所需的额外网络传输越多。
; 如果发现无法解释的速度降低,可以尝试将此值增加到32768。
memcache.chunk_size = 8192
; 连接到memcached服务器时使用的默认TCP端口。
memcache.default_port = 11211
; 控制将key映射到server的策略。默认值"standard"表示使用先前版本的老hash策略。
; 设为"consistent"可以允许在连接池中添加/删除服务器时不必重新计算key与server之间的映射关系。
;memcache.hash_strategy = "standard"; 控制将key映射到server的散列函数。默认值"crc32"使用CRC32算法,而"fnv"则表示使用FNV-1a算法。
; FNV-1a比CRC32速度稍低,但是散列效果更好。
;memcache.hash_function = "crc32"
3. 通过下面一段简单的代码来测试上面配置的含义
<?php
ini_set("memcache.allow_failover",1);
ini_set("memcache.max_failover_attempts", 2);
$a = new Memcache();
$a->addServer("10.1.1.181",11251);
$a->addServer("10.1.1.181",11252);
$a->addServer("10.1.1.181",11253);
$a->addServer("10.1.1.181",11254);
$a->add("a","A",0);
?>
其中: 10.1.1.181 是一个不存在的IP,就算是存在,相应的端口也没有提供服务,目的就是要让连接失败。
当:
ini_set("memcache.allow_failover",0);
时, 我们可以通过tcpdump发现,只连接了一次,失败后就退出了
当:
ini_set("memcache.allow_failover",1);
ini_set("memcache.max_failover_attempts", 20);
时,我们可以通过tcpdump发现,四个端口都被尝试了一次,虽然设置了20次,但是不会循环回来尝试直到20次
当:
ini_set("memcache.allow_failover",1);
ini_set("memcache.max_failover_attempts", 2);
时: 我们可以通过tcpdump发现,两个端口都被尝试失败后退出
4. PHP以前的memcache模块没有使用一致性hash,后来添加了该hash算法,但是默认没有使用,需要配置,如:
memcache.hash_strategy = consistent
或者使用ini_set("memcache.hash_strategy","consistent");
可以通过下面代码来验证一致性hash的好处: <?php
//ini_set("memcache.hash_strategy","consistent");
$a = new Memcache();
$a->addServer("10.55.38.18",11271);
$a->addServer("10.55.38.18",11272);
$a->addServer("10.55.38.18",11273);
$a->addServer("10.55.38.18",11274);
$a->addServer("10.55.38.18",11275);
$a->addServer("10.55.38.18",11276);
for($i = 0; $i < 1000; $i++) {
$a->set("key".$i,$i,0);
}
$b = new Memcache();
$b->addServer("10.55.38.18",11271);
$b->addServer("10.55.38.18",11272);
$b->addServer("10.55.38.18",11273);
$b->addServer("10.55.38.18",11274);
$b->addServer("10.55.38.18",11275);
for($i = 0; $i < 1000; $i++) {
if($b->get("key".$i)) $m++;
}
echo "all: $in";
echo "hits: $mn";
for($i = 0; $i < 1000; $i++) {
$a->delete("key".$i);
}
?>
未使用一致性hash的结果为:
all: 1000
hits: 134使用一致性hash的结果为:
all: 1000
hits: 838
6个节点中,损坏一个节点后,损失数据为: 16.2 约等于 1/6
5. PHP还有一个libmemcached的模块, 也实现了一致性的hash,效果和memcache中实现的基本一样(似乎不同,为测试,因为现在还没有这个需求); 而且还可以设置OPT_LIBKETAMA_COMPATIBLE, libmemcached下载: http://pecl.php.net/package/memcached
下面是关于libmemcached的一致性hash的测试, 从这里我们也发现,CONSISTENT不是一种
hash算法,而是一种DISTRIBUTION
<?php
$a = new Memcached();
$a->setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT);
$a->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
$a->addServer("10.55.38.18",11271);
$a->addServer("10.55.38.18",11272);
$a->addServer("10.55.38.18",11273);
$a->addServer("10.55.38.18",11274);
$a->addServer("10.55.38.18",11275);
$a->addServer("10.55.38.18",11276);
for($i = 0; $i < 1000; $i++) {
$a->set("key".$i,$i,0);
}
$b = new Memcached();
$b->setOption(Memcached::OPT_DISTRIBUTION,Memcached::DISTRIBUTION_CONSISTENT);
$b->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
$a->addServer("10.55.38.18",11271);
$b->addServer("10.55.38.18",11271);
$b->addServer("10.55.38.18",11272);
$b->addServer("10.55.38.18",11273);
$b->addServer("10.55.38.18",11274);
$b->addServer("10.55.38.18",11275);
for($i = 0; $i < 1000; $i++) {
if($b->get("key".$i)) $m++;
}
echo "all: $in";
echo "hits: $mn";
for($i = 0; $i < 1000; $i++) {
$a->delete("key".$i);
}
?>
6. 关于CONSISTENT
的使用也要慎用,这个算法是比较消耗cpu的,我们的一个业务在使用CONSISTENT
算法时,服务器每秒处理20个请求; 而去掉该算法后,每秒可以处理300多个请求,所以说这个算法对性能的影响还是蛮大的;
关于CONSISTENT的用法在网上说的比较少,我这些都是从源码里发现的,分享给大家。
7. 关于 OPT_COMPRESSION 的一点说明:
在libmemcached里面可以根据该选项来指定压缩或不压缩,但是如果原始内容小于100字节,就算指定压缩了,也不会压缩的(源码里面就是这么写的,文档中也这么说明了),因为太小了; 这似乎是一种明智的做法;
在memcache中也可以通过函数来设置setCompressThreshold( int threshold [, float min_savings] ); 但是如果不设置,则默认值为0; 即:不管原始内容是多少都要压缩的。好像就有些不够明智了。不过也可能正好能满足某些人的需求。