PHP 之memcache使用

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; 即:不管原始内容是多少都要压缩的。好像就有些不够明智了。不过也可能正好能满足某些人的需求。

留下评论

邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据