Hello,
I am a newcomer in Drupal 8 and I was looking for a faster caching solution using memcache or other memory cache solution on Drupal 8. I though that memcache module could be a nice solution for our website as we are currently using memcached as it's newer and faster than memcache especially when you are using persistent connections.
But I discovered that the module memcache did not support the persistent connections for memcached and after a look in the code, I think I understood the problem: you have to check if memcached has already some persistent connections before adding some fresh ones (I ended with the same problem in other projects ;).
Also, if you want to add more than one server in memcached, you should use addservers when using '\Memcached::DISTRIBUTION_CONSISTENT'... see https://www.php.net/manual/en/memcached.addserver.php
I have just rewritten the MemcachedConnection Class without testing it to provide you with an example of how you could change the implementation of the MemcachedConnection:
/**
* Class MemcachedConnection.
*/
class MemcachedConnection implements MemcacheConnectionInterface {
/**
* The memcache object.
*
* @var \Memcached
*/
protected $memcache;
/**
* The memcache config
*
* @var MemcacheSettings
*/
protected $settings;
/**
* The memcache serveur list
*/
protected $servers = [];
protected $isPersistent;
/**
* Constructs a MemcachedConnection object.
*
* @param \Drupal\memcache\MemcacheSettings $settings
* The memcache config object.
*/
public function __construct(MemcacheSettings $settings) {
$this->settings = $settings;
$this->isPersistent = FALSE;
}
/**
* {@inheritdoc}
*/
public function addServer($server_path, $persistent = FALSE) {
list($host, $port) = explode(':', $server_path);
if ($host == 'unix') {
// Memcached expects just the path to the socket without the protocol.
$host = substr($server_path, 7);
// Port is always 0 for unix sockets.
$port = 0;
}
//The third argument of Memcached::addServer is for the server weight, not the persistence...
$this->servers[] = [$host, $port];
return TRUE;
}
/**
* {@inheritdoc}
*/
public function getMemcache() {
if (!isset($this->memcache)) {
$this->createMemcache();
}
return $this->memcache;
}
/**
* {@inheritdoc}
*/
public function close() {
if (!$this->isPersistent) {
$this->memcache->quit();
}
}
protected function createMemcache() {
$persistentId = $this->settings->get('persistent_id')??false;
//$persistentId must be a string
if (!empty($persistentId)) {
$this->memcache = new \Memcached((string)$persistentId);
$this->isPersistent = TRUE;
}
else {
$this->memcache = new \Memcached();
}
if (!$this->isPersistent || !!count($this->memcache->getServerList())) {
$default_opts = [
\Memcached::OPT_COMPRESSION => TRUE,
\Memcached::OPT_DISTRIBUTION => \Memcached::DISTRIBUTION_CONSISTENT,
];
foreach ($default_opts as $key => $value) {
$this->memcache->setOption($key, $value);
}
// See README.txt for setting custom Memcache options when using the
// memcached PECL extension.
foreach ($this->settings->get('options', []) as $key => $value) {
$this->memcache->setOption($key, $value);
}
// SASL configuration to authenticate with Memcached.
// Note: this only affects the Memcached PECL extension.
if ($sasl_config = $this->settings->get('sasl', [])) {
$this->memcache->setSaslAuthData($sasl_config['username'], $sasl_config['password']);
}
$this->memcache->addServers($this->servers);
}
}
}
Comments
Comment #2
ndobromirov commentedLet's unify the solution for persistent connections.
I am marking this as duplicate of #3058121: MemcacheD with persistent connections, due to being the same feature request, but opened much later.
Comment #3
ndobromirov commented