public function __construct($conf = false)
{
$this->conf = $conf ? $conf : Config::get('default_cache');
if (extension_loaded('Memcached')) {
$this->memcache = new \Memcached('cml_memcache_pool');
$this->type = 1;
} elseif (extension_loaded('Memcache')) {
$this->memcache = new \Memcache();
$this->type = 2;
} else {
throw new PhpExtendNotInstall(Lang::get('_CACHE_EXTEND_NOT_INSTALL_', 'Memcached/Memcache'));
}
if (!$this->memcache) {
throw new PhpExtendNotInstall(Lang::get('_CACHE_NEW_INSTANCE_ERROR_', 'Memcache'));
}
$singleNodeDownFunction = function ($host, $port) {
//这边挂掉调用此回调在几s内只会调用一次。其它情况使用memcache方法均返回flase不报错
Plugin::hook('cml.cache_server_down', ['host' => $host, 'port' => $port]);
Log::emergency('memcache server down', ['downServer' => ['host' => $host, 'port' => $port]]);
};
$allNodeDownFunction = function ($serverList) {
Plugin::hook('cml.cache_server_down', $this->conf['server'], $serverList);
//全挂
throw new CacheConnectFailException(Lang::get('_CACHE_CONNECT_FAIL_', 'Memcache', json_encode($serverList)));
};
$downServer = 0;
if ($this->type == 2) {
//memcache
foreach ($this->conf['server'] as $val) {
if (!$this->memcache->addServer($val['host'], $val['port'])) {
Log::emergency('memcache server down', ['downServer' => $val]);
}
}
$this->memcache->setFailureCallback($singleNodeDownFunction);
$serverList = $this->memcache->getextendedstats();
foreach ($serverList as $server => $status) {
$status || $downServer++;
}
if (count($serverList) <= $downServer) {
$allNodeDownFunction($serverList);
}
return;
}
if (md5(json_encode($this->conf['server'])) !== md5(json_encode($this->memcache->getServerList()))) {
$this->memcache->quit();
$this->memcache->resetServerList();
$this->memcache->addServers(array_values($this->conf['server']));
$this->memcache->setOptions([\Memcached::OPT_PREFIX_KEY => $this->conf['prefix'], \Memcached::OPT_DISTRIBUTION => \Memcached::DISTRIBUTION_CONSISTENT, \Memcached::OPT_LIBKETAMA_COMPATIBLE => true, \Memcached::OPT_SERVER_FAILURE_LIMIT => 1, \Memcached::OPT_RETRY_TIMEOUT => 30, \Memcached::OPT_AUTO_EJECT_HOSTS => true, \Memcached::OPT_REMOVE_FAILED_SERVERS => true]);
\Memcached::HAVE_JSON && $this->memcache->setOption(\Memcached::OPT_SERIALIZER, \Memcached::SERIALIZER_JSON_ARRAY);
}
$serverStatus = $this->memcache->getStats();
foreach ($serverStatus as $server => $status) {
if ($status['pid'] < 1) {
$downServer++;
$server = explode(':', $server);
$singleNodeDownFunction($server[0], $server[1]);
}
}
if (count($serverStatus) <= $downServer) {
$allNodeDownFunction($serverStatus);
}
}