From 5f0cff88022b0dbc1ab1a21958d4bddcb09f70e5 Mon Sep 17 00:00:00 2001 From: Oliver Stark Date: Mon, 14 Oct 2019 14:27:36 +0200 Subject: [PATCH] Use proper redundancy options to make a failover seamless --- composer.json | 2 +- src/Bootstrap.php | 42 +++++++++++++++++++++++++++++++++++++++--- src/init.php | 2 ++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 23d2d1f..704919b 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "fortrabbit/yii-memcached", "description": "Memcached Session & Cache for Craft3 / Yii2 on fortrabbit", - "version": "1.0.0", + "version": "1.1.0", "type": "yii2-extension", "keywords": ["yii2", "craftcms", "caching", "cache", "memcached", "memcache", "session"], diff --git a/src/Bootstrap.php b/src/Bootstrap.php index 3d49f79..7947230 100644 --- a/src/Bootstrap.php +++ b/src/Bootstrap.php @@ -15,6 +15,8 @@ class Bootstrap implements BootstrapInterface { + const TIMEOUT_IN_MILLISECONDS = 50; + /** * Bootstrapper * @@ -31,6 +33,7 @@ public function bootstrap($app) 'class' => MemCache::class, 'persistentId' => getenv('MEMCACHE_PERSISTENT') ? 'cache' : null, 'servers' => $this->getMemcachedServers(), + 'options' => $this->getOptions(), 'useMemcached' => true ]); } catch (InvalidConfigException $e) { @@ -51,13 +54,46 @@ protected function getMemcachedServers(): array $servers[] = [ 'host' => getenv('MEMCACHE_HOST' . $num), 'port' => getenv('MEMCACHE_PORT' . $num), - 'retryInterval' => 2, - 'status' => true, - 'timeout' => 2, 'weight' => 1, ]; } return $servers; } + + /** + * @return array + */ + protected function getOptions(): array + { + if (!extension_loaded('memcached')) { + return []; + } + + return [ + + // Assure that dead servers are properly removed and ... + \Memcached::OPT_REMOVE_FAILED_SERVERS => true, + + // ... retried after a short while (here: 2 seconds) + \Memcached::OPT_RETRY_TIMEOUT => 2, + + // KETAMA must be enabled so that replication can be used + \Memcached::OPT_LIBKETAMA_COMPATIBLE => true, + + // Replicate the data, i.e. write it to both memcached servers + \Memcached::OPT_NUMBER_OF_REPLICAS => 1, + + // Those values assure that a dead (due to increased latency or + // really unresponsive) memcached server increased dropped fast + // and the other is used. + \Memcached::OPT_POLL_TIMEOUT => self::TIMEOUT_IN_MILLISECONDS, // milliseconds + \Memcached::OPT_SEND_TIMEOUT => self::TIMEOUT_IN_MILLISECONDS * 1000, // microseconds + \Memcached::OPT_RECV_TIMEOUT => self::TIMEOUT_IN_MILLISECONDS * 1000, // microseconds + \Memcached::OPT_CONNECT_TIMEOUT => self::TIMEOUT_IN_MILLISECONDS, // milliseconds + + // Further performance tuning + \Memcached::OPT_NO_BLOCK => true, + ]; + } } diff --git a/src/init.php b/src/init.php index 689b03c..f26f087 100644 --- a/src/init.php +++ b/src/init.php @@ -12,11 +12,13 @@ // session config ini_set('session.save_handler', 'memcached'); ini_set('session.save_path', implode(',', $handlers)); + ini_set('memcached.sess_locking', 0); if (getenv('MEMCACHE_COUNT') == 2) { ini_set('memcached.sess_number_of_replicas', 1); ini_set('memcached.sess_consistent_hash', 1); ini_set('memcached.sess_binary', 1); + ini_set('memcached.sess_remove_failed_servers', 1); } }