сохранение memcached в PHP не работает должным образом

Я немного поиграл с другой библиотекой memcached и версией плагина, чтобы обеспечить реальное постоянство между клиентом PHP memcache и сервером memcached.

Проблема в том, что все еще соединения открываются и закрываются, так что счетчик соединений увеличивается вместо повторного использования существующего постоянного соединения.

Я скомпилировал демон memcached из новейшего источника на машине RedHat. Я использую версию memcached-1.4.14 и начал с "#/opt/memcached/bin/memcached -vvvv"

Плагин php, который я также скомпилировал из новейшей исходной версии memcached-2.0.1, я скомпилировал его с 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 (Сантьяго)
  • PHP версии 5.3.3
  • Apache/2.2.15 в префорке
  • Кэш-сервер 1.4.14
  • либмемкэш 1.0.9
  • Плагин PHP memcached 2.0.1

person Artur Wawrzynkiewicz    schedule 01.08.2012    source источник
comment
Это интересно. Я полагаю, что использую какую-то старую версию плагина memcache php, но обычно использую только 4 функции. connect, get, set и flush. обычно скрипт на моем сервере создает сервер memcache, если он не запущен.   -  person SharkyLV    schedule 01.08.2012
comment
Сколько prefork-серверов у вас работает в любой момент времени? У вас может быть столько постоянных подключений, сколько у вас запущено родительских серверов. Допустим, у вас есть 20 StartServers и 50 потоков на сервер, каждый из этих 20 серверов может иметь собственное постоянное соединение с memcached, а 50 дочерних потоков для каждого сервера будут использовать постоянное соединение своего родителя. Совпадают ли PID этих соединений с PID каждого из ваших дочерних процессов?   -  person drew010    schedule 08.08.2012


Ответы (2)


Это потому, что вы устанавливаете 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() );
?>
person Patrick Allaert    schedule 18.12.2012
comment
Меня это устраивает, спасибо за решение проблемы. Я понимаю, что в режиме prefork apache открываются два соединения для каждого дочернего процесса apache, что кажется нормальным поведением. Я вижу в журнале подключений: #netstat -n|grep 11211|grep ::|wc -l 60, и это соответствует процессам apache #ps uax|grep httpd|wc -l 31 (основной процесс и 30 дочерних процессов) - person Artur Wawrzynkiewicz; 19.12.2012
comment
Заканчивались локальные порты. Ваш ответ спас мой день. Большое спасибо! - person Bhaskar Choudhary; 08.02.2019

Я не верю, что с помощью расширения Memcached можно добиться настоящего персистентного состояния. Из постоянной документации PHP:

Если вы используете PHP-CGI

Постоянное соединение может быть общим для всего процесса приложения, но оно будет закрыто по завершению скрипта (загрузка страницы);

Если вы используете многопроцессорный модуль Apache

Запрос вызовет дочерний процесс с постоянным соединением. Если поступает новый запрос, а предыдущий еще не завершен, будет использоваться существующее постоянное соединение. Однако, если не будет сделано никаких дополнительных запросов, постоянное соединение будет закрыто после завершения дочернего процесса.

Предоставленный вами сценарий может быть эффективным при тестировании memcached, но запуск его вручную может оказаться неточным. Взгляните на jMeter. Вы можете быстро создать группу потоков и создать более 100 пользователя в вашем приложении.

person emcconville    schedule 07.08.2012
comment
Да, настоящие постоянные соединения поддерживаются расширением Memcached. - person Patrick Allaert; 18.12.2012