3

I have a problem with Memcached persistence in PHP. Memcached lib returns empty getServerList() until there are 10 concurrent connections. Couldn't find sensible explanation of that, but found people with the same problem (without solution).

My example:

class Cache {

    protected $memcached;

    public function __construct($cache_name) {
        $instance_name = 'persistent-' . $cache_name;
        $this->memcached = new Memcached($instance_name);
        $server_count = count($this->memcached->getServerList());
        echo '[MC] Server count of ', $instance_name, ': ', $server_count, PHP_EOL;

        if (0 == $server_count) {
            $servers = array(array("localhost","16586"),array("localhost","16587"));
            echo '[MC] Adding servers: ', json_encode($servers), PHP_EOL;
            // options don't change anything in my case
            $this->memcached->setOptions(array(
                Memcached::OPT_DISTRIBUTION => Memcached::DISTRIBUTION_CONSISTENT,
                Memcached::OPT_LIBKETAMA_COMPATIBLE => true
            ));
            $this->memcached->addServers($servers);
        }

        $stats = $this->memcached->getStats();
        foreach($stats as $server => $data){
            echo '[MC] Stats of ', $server, ' curr_connections: ', $data['curr_connections'], ' total_connections: ', $data['total_connections'], PHP_EOL;
        }
    }

    public function get($key) {
        echo '[MC] Server for key: ', $key, ' is ', json_encode($this->memcached->getServerByKey($key)), PHP_EOL;
        $ret = $this->memcached->get($key);
        echo '[MC] Getting ', $key, ' with result: ', $ret, PHP_EOL;
        return $ret;
    }

    public function set($key, $data, $timeout = 0) {
        echo '[MC] Set of ', $key, ' with data: ', $data, PHP_EOL;
        return $this->memcached->set($key, $data, $timeout);
    }
}

$cache = new Cache('instance');

$ret = $cache->get('something');

if(empty($ret)) {
    $cache->set('something', true);
}

What I expect from this code is single addServers run after connections are established.

Fresh run (after memcached/apache restart) shows:

// first run
[MC] Server count of persistent-instance: 0
[MC] Adding servers: [["localhost","16586"],["localhost","16587"]]
[MC] Stats of localhost:16586 curr_connections: 5 total_connections: 6
[MC] Stats of localhost:16587 curr_connections: 5 total_connections: 6
[MC] Server for key: something is {"host":"localhost","port":16587,"weight":1}
[MC] Getting something with result: 
[MC] Set of something with data: 1

// second
[MC] Server count of persistent-instance: 0
[MC] Adding servers: [["localhost","16586"],["localhost","16587"]]
[MC] Stats of localhost:16586 curr_connections: 6 total_connections: 7
[MC] Stats of localhost:16587 curr_connections: 6 total_connections: 7
[MC] Server for key: something is {"host":"localhost","port":16587,"weight":1}
[MC] Getting something with result: 1

// up to 6th call curr_connections are growing and still adding servers to pool
[MC] Server count of persistent-instance: 0
[MC] Adding servers: [["localhost","16586"],["localhost","16587"]]
[MC] Stats of localhost:16586 curr_connections: 10 total_connections: 11
[MC] Stats of localhost:16587 curr_connections: 10 total_connections: 11
[MC] Server for key: something is {"host":"localhost","port":16587,"weight":1}
[MC] Getting something with result: 1

// 7th+ call finally with expected result
[MC] Server count of persistent-instance: 2
[MC] Stats of localhost:16586 curr_connections: 10 total_connections: 11
[MC] Stats of localhost:16587 curr_connections: 10 total_connections: 11
[MC] Server for key: something is {"host":"localhost","port":16587,"weight":1}
[MC] Getting something with result: 1

Am I missing something? What's happening?

My config:

  • Ubuntu 13.04
  • Apache 2.2.22
  • Memcached server 1.4.14 (4 instances)
  • libmemcached 1.0.8
  • PHP 5.4.9-4ubuntu2.3
  • Memcached lib for PHP latest.

UPDATE 2014.04.22

The problem still exists on my latest config:

  • Xubuntu 13.10 (kernel 3.11.0-19)
  • Apache 2.4.6
  • Memcached 1.4.14
  • libmemcached 1.0.8
  • PHP 5.5.3-1ubuntu2.3
  • Memcached lib for PHP 2.1.0
s3m3n
  • 4,187
  • 1
  • 28
  • 24

2 Answers2

1

Im not sure I see what your "problem" is. Each of your Apache PHP "servers" (i.e. child workers) when they start have not yet connected to memcache - so each needs to initialise a connection - they each do... once.

Now each worker has a server list.

if you were to query it a 2nd time - you would "see" the server list.. but you have a cache object that I'm presuming you only instantiate once. So you never call it a second time, so it would never attempt to call the getServers a second time... so you would never see a "here is the server list".

Do I have that correctly?

If so, it is one of the common problems/misconceptions about "singletons". The most important question you always need to ask about singletons is "How many of them are there" - because they are only "single" in the context they control.... but as in this case - other external factors may make more of them. In this case there is one per PHP instance.... but your apache makes multiple PHP instances - so there will be one each - and those share nothing, so each needs its own globals, its own persistent connection to database, persistent connection to memcache etc etc.

Very happy to be corrected.

Meh-Lindi
  • 29
  • 6
0

If you are using php-fpm (or a similar config with Apache), each php child will create its own persistent connection to memcache. So if php-fpm is configured to create 10 child, your log output makes fully sense :-)