Exemplo n.º 1
0
 /**
  * 根据key获取redis实例
  * 这边还是用取模的方式,一致性hash用php实现性能开销过大。取模的方式对只有几台机器的情况足够用了
  * 如果有集群需要,直接使用redis3.0+自带的集群功能就好了。不管是可用性还是性能都比用php自己实现好
  *
  * @param $key
  *
  * @return \Redis
  */
 private function hash($key)
 {
     $success = sprintf('%u', crc32($key)) % count($this->conf['server']);
     if (!isset($this->redis[$success]) || !is_object($this->redis[$success])) {
         $instance = new \Redis();
         if ($instance->pconnect($this->conf['server'][$success]['host'], $this->conf['server'][$success]['port'], 1.5)) {
             $this->redis[$success] = $instance;
         } else {
             \Cml\throwException(Lang::get('_CACHE_CONNECT_FAIL_', 'Redis', $this->conf['server'][$success]['host'] . ':' . $this->conf['server'][$success]['port']));
         }
         if (isset($this->conf['server'][$success]['password']) && !empty($this->conf['server'][$success]['password'])) {
             $instance->auth($this->conf['server'][$success]['password']) || \Cml\throwException('redis password error!');
         }
     }
     return $this->redis[$success];
 }
Exemplo n.º 2
0
 /**
  * 根据key获取redis实例
  * 这边还是用取模的方式,一致性hash用php实现性能开销过大。取模的方式对只有几台机器的情况足够用了
  * 如果有集群需要,直接使用redis3.0+自带的集群功能就好了。不管是可用性还是性能都比用php自己实现好
  *
  * @param $key
  *
  * @return \Redis
  */
 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];
 }