Problem introduction
Recently, some PHP users provided feedback on the performance testing results of ApsaraDB for Memcache, which did not meet the expected performance metrics. Upon understanding the specific situation, most users connect to ApsaraDB for Memcache through Apache web service using short-lived connections. Each short-lived connection incurs overhead not only from socket reconnection but also from a complex re-authentication procedure, which is much more costly than a regular request. Therefore, it significantly impacts the efficiency of the website.
Solution
We suggest users switch from short-lived connections to persistent connections. However, ApsaraDB for Memcache requires the use of the PHP Memcached extension, which does not have a pconnect interface like the memcache extension. How can you establish a persistent connection in PHP? The following tutorials are provided for your reference.
On the PHP official website, when introducing the Memcached constructor, there is the following statement:
Description
Memcached::__construct ([ string $persistent_id ] ) creates a Memcached instance representing a connection to the Memcached server.
Parameters
persistent_id By default, the Memcached instance is destroyed after the request ends. However, you can specify a unique ID for each instance using persistent_id during creation to share the instance between requests. All instances created with the same persistent_id value share the same connection.
By passing the same persistent_id to the constructor, you can achieve a shared connection. The code implementation is as follows:
<?php
$memc = new Memcached(‘ocs’);//Here, ‘ocs’ is the persistent_id
if (count($memc->getServerList()) == 0) /*Before establishing a connection, check first*/
{
echo "New connection"."<br>";
/*All options must be placed inside the check because some options may cause reconnection, turning a persistent connection into a short-lived connection!*/
$memc->setOption(Memcached::OPT_COMPRESSION, false);
$memc->setOption(Memcached::OPT_BINARY_PROTOCOL, true);
$memc->setOption(Memcached::OPT_TCP_NODELAY, true); //Important, PHP Memcached has a bug where if the value of get does not exist, there is a fixed 40ms latency. Enabling this parameter can avoid this bug.
/* addServer code must be inside the check. Otherwise, it is equivalent to repeatedly establishing the ‘ocs’ connection pool, which may cause abnormal client PHP programs*/
$memc->addServer("your_ip", 11212);
$memc->setSaslAuthData("user", "password");
}
else
{
echo "Now connections is:".count($memc->getServerList())."<br>";
}
$memc->set("key", "value");
echo "Get from OCS: ".$memc->get("key");
//$memc->quit();/*Do not add quit at the end of the code. Otherwise, it becomes a short-lived connection!*/
?>
Three important points in the above code are annotated. The keyword “ocs” in the constructor is equivalent to a connection pool. You can obtain a connection from the pool by calling new Memcached(‘ocs’) for the connection you need.
Execution result
Place the above code in the Apache working path /var/www/html/ and name it test.php. Then enter in the browser: http://your_ip:80/test.php. The output result in the browser for the first 8 times is:
New connection
Get from OCS: value
This means that these 8 times are all new connections, and after 8 times, these 8 connections are reused. The packet capture results also show that after 8 times, they are all persistent connections, with no socket reconnection or re-authentication.
Why are there 8 connections? By checking the httpd.conf configuration file, it is because Apache started 8 child processes:
#StartServers: numbers of server processes to start
StartServers 8
Thus, 8 connections are initialized in the ‘ocs’ persistent_id connection pool, and subsequent requests use these 8 connections.
Next, test page redirection. Copy a PHP file, and the persistent_id of the connection constructor is still “ocs”. The result is that the connection switches from one to another (because different Apache child processes are called), but there is no re-authentication or socket reconnection process. This means that the PHP Memcached persistent connection setting is valid. Usually, we use the PHP-FPM pattern. The FPM process maintains a persistent connection with the Memcached server, so the lifecycle of this connection is the same as the Apache process.