private function hash($key)
{
$serverNum = count($this->conf['server']);
$success = sprintf('%u', crc32($key)) % $serverNum;
if (!isset($this->redis[$success]) || !is_object($this->redis[$success])) {
$instance = new \Redis();
$connectToRedisFunction = function ($host, $port, $isPersistentConnect) use($instance) {
if ($isPersistentConnect) {
return $instance->pconnect($host, $port, 1.5);
} else {
return $instance->connect($host, $port, 1.5);
}
};
$isPersistentConnect = !(isset($this->conf['server'][$success]['pconnect']) && $this->conf['server'][$success]['pconnect'] === false);
$connectResult = $connectToRedisFunction($this->conf['server'][$success]['host'], $this->conf['server'][$success]['port'], $isPersistentConnect);
$failOver = null;
if (!$connectResult && !empty($this->conf['back'])) {
$failOver = $this->conf['back'];
$isPersistentConnect = !(isset($failOver['pconnect']) && $failOver['pconnect'] === false);
$connectResult = $connectToRedisFunction($failOver['host'], $failOver['port'], $isPersistentConnect);
}
if (!$connectResult && $serverNum > 1) {
$failOver = $success + 1;
$failOver >= $serverNum && ($failOver = $success - 1);
$failOver = $this->conf['server'][$failOver];
$isPersistentConnect = !(isset($failOver['pconnect']) && $failOver['pconnect'] === false);
$connectResult = $connectToRedisFunction($failOver['host'], $failOver['port'], $isPersistentConnect);
}
if (!$connectResult) {
Plugin::hook('cml.cache_server_down', [$this->conf['server'][$success]]);
throw new CacheConnectFailException(Lang::get('_CACHE_CONNECT_FAIL_', 'Redis', $this->conf['server'][$success]['host'] . ':' . $this->conf['server'][$success]['port']));
}
$password = false;
if (is_null($failOver)) {
if (isset($this->conf['server'][$success]['password']) && !empty($this->conf['server'][$success]['password'])) {
$password = $this->conf['server'][$success]['password'];
}
isset($this->conf['server'][$success]['db']) && $instance->select($this->conf['server'][$success]['db']);
} else {
if (isset($failOver['password']) && !empty($failOver['password'])) {
$password = $failOver['password'];
}
isset($failOver['db']) && $instance->select($failOver['db']);
Log::emergency('redis server down', ['downServer' => $this->conf['server'][$success], 'failOverTo' => $failOver]);
Plugin::hook('cml.redis_server_down_fail_over', ['downServer' => $this->conf['server'][$success], 'failOverTo' => $failOver]);
}
if ($password && !$instance->auth($password)) {
throw new \RuntimeException('redis password error!');
}
$instance->setOption(\Redis::OPT_PREFIX, $this->conf['prefix']);
$this->redis[$success] = $instance;
}
return $this->redis[$success];
}