PHP中的memcached持久性无法按预期工作


memcached persistence in PHP does not work as expected

我已经尝试了不同的memcached库和插件版本,以实现PHP memcached客户端和memcached服务器之间的真正持久性。

问题是,静态连接是打开和关闭的,因此连接计数器会上升,而不是重新使用现有的持久连接。

我已经在一台redhat机器上从最新的源代码编译了memcached守护进程。我使用memcached-1.4.14版本,并从"#/opt/memcached/bin/memcached-vvv"开始

我还从最新的源代码版本memcached-2.0.1编译了php插件,我根据libmemcached-1.0.9编译了它,使其保持最新。目前,它还没有针对libmemcached-1.0.10进行编译。

我的PHP脚本如下:

<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
$key = "key_" . uniqid();
$memcached = new Memcached( 'persistent' );
$memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
$memcached->setOption(Memcached::OPT_RECV_TIMEOUT, 1000);
$memcached->setOption(Memcached::OPT_SEND_TIMEOUT, 3000);
$memcached->setOption(Memcached::OPT_TCP_NODELAY, true);
$memcached->setOption(Memcached::OPT_PREFIX_KEY, 'persistent');
if( !count($memcached->getServerList() ) )
{
    $memcached->addServer( 'localhost', 11211 );
}
$memcached->set($key, 'value');
$value = $memcached->get($key);
print_r( $memcached->getStats() );
?>

在启动脚本时,我在输出中看到,服务器不会被添加,只是在超时之后。

Array ( [@�qVG:11211] => Array ( [pid] => 3728 [uptime] => 73 [threads] => 4 [time] => 1343813688 [pointer_size] => 64 [rusage_user_seconds] => 0 [rusage_user_microseconds] => 6998 [rusage_system_seconds] => 0 [rusage_system_microseconds] => 31995 [curr_items] => 37 [total_items] => 37 [limit_maxbytes] => 67108864 [curr_connections] => 38 [total_connections] => 47 [connection_structures] => 39 [bytes] => 3589 [cmd_get] => 37 [cmd_set] => 37 [get_hits] => 37 [get_misses] => 0 [evictions] => 0 [bytes_read] => 3267 [bytes_written] => 39458 [version] => 1.4.14 ) )

但是连接计数器仍然会上升,我假设客户端创建了一个连接,并且在服务器端重新使用了持久连接。

#netstat -an | grep 11211 | wc -l
tcp        0      0 ::1:11211                   ::1:55941                   VERBUNDEN   
tcp        0      0 ::1:55961                   ::1:11211                   VERBUNDEN   
tcp        0      0 ::1:55959                   ::1:11211                   VERBUNDEN   
tcp        0      0 ::1:11211                   ::1:56005                   VERBUNDEN   
...and so on

在服务器端,我得到了冗长的输出,告诉使用了持久性:

...
<43 get persistentkey_5018f83903ded
> FOUND KEY persistentkey_5018f83903ded
>43 sending key persistentkey_5018f83903ded
>43 END
...

我们希望在具有大量独立连接的高性能环境中使用memcache,而连接数量目前确实会扼杀apache的子级。有什么想法可以让你真正坚持下去吗?

使用的软件:

  • Red Hat Enterprise Linux Server 6.2版(Santiago)
  • PHP 5.3.3版
  • Prework中的Apache/2.2.15
  • Memcache服务器1.4.14
  • libmemcached 1.0.9
  • PHP memcached插件2.0.1

这是因为您在每次请求时都设置Memcached::OPT_TCP_NODELAY。像这样的一些选项会导致libmemcached库在您设置它的时候执行重新连接

由于连接选项一直存在,因此没有理由在每次请求时都设置它们。因此,您应该使用:

<?php
header("Cache-Control: no-cache, must-revalidate");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
$key = "key_" . uniqid();
$memcached = new Memcached( 'persistent' );
if( !count($memcached->getServerList() ) )
{
    $memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);
    $memcached->setOption(Memcached::OPT_RECV_TIMEOUT, 1000);
    $memcached->setOption(Memcached::OPT_SEND_TIMEOUT, 3000);
    $memcached->setOption(Memcached::OPT_TCP_NODELAY, true);
    $memcached->setOption(Memcached::OPT_PREFIX_KEY, 'persistent');
    $memcached->addServer( 'localhost', 11211 );
}
$memcached->set($key, 'value');
$value = $memcached->get($key);
print_r( $memcached->getStats() );
?>

我不相信使用Memcached扩展可以实现real持久化。来自PHP的持久文档:

如果您使用PHP-CGI

持久连接可以在整个应用程序过程中共享,但在脚本完成(页面加载)时将关闭;

如果您正在使用Apache的多进程模块

请求将派生出具有持久连接的子进程。如果有新的请求传入,而上一个请求尚未完成,则将使用现有的持久连接。但是,如果没有发出额外的请求,那么在子进程完成时,持久连接将关闭。

您提供的脚本在测试memcached时可能有效,但手动运行可能无效。看看jMeter。您可以快速创建一个线程组,并向您的应用程序抛出一个100多个用户。