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

pjost created an issue. See original summary.

ndobromirov’s picture

Status: Active » Closed (duplicate)

Let'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.

ndobromirov’s picture