common/file/FSOFRedis.php (182 lines of code) (raw):

<?php /** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ namespace com\fenqile\fsof\common\file; use com\fenqile\fsof\common\config\FSOFConstants; class FSOFRedis { private static $_instance; private $m_redis = null; private $logger; private $connect_timeout = 1; private $read_timeout = 2; private $retry_count = 1; private $connect_type = FSOFConstants::FSOF_SERVICE_REDIS_CONNECT_TYPE_TCP; private $hosts = [ [FSOFConstants::FSOF_SERVICE_REDIS_HOST, FSOFConstants::FSOF_SERVICE_REDIS_PORT], ]; public static function instance($config = []) { if (extension_loaded('redis')) { if (!isset(FSOFRedis::$_instance)) { FSOFRedis::$_instance = new FSOFRedis($config); FSOFRedis::$_instance->get_redis(); } return FSOFRedis::$_instance; } else { \Logger::getLogger(__CLASS__)->error("not installed redis extension"); } return NULL; } public function __construct($config = []) { $this->logger = \Logger::getLogger(__CLASS__); if(isset($config['redis_hosts'])) { $this->hosts = []; $address = explode(',', $config['redis_hosts']); foreach ($address as $node){ list($host, $port) = explode(':', $node); $this->hosts[] = [$host, $port??FSOFConstants::FSOF_SERVICE_REDIS_PORT]; } } if(isset($config['redis_connect_timeout'])) { $this->connect_timeout = $config['redis_connect_timeout']; } if(isset($config['redis_read_timeout'])) { $this->read_timeout = $config['redis_read_timeout']; } if(isset($config['redis_connect_type'])) { $this->connect_type = $config['redis_connect_type']; } if(isset($config['redis_retry_count'])) { $this->retry = min($config['redis_retry_count'], 1); } } public function get_redis() { if (!isset($this->m_redis)) { $hosts_count = count($this->hosts); $retry = $this->retry_count; $rand_num = rand() % $hosts_count; $ret = false; do{ try{ $redis_cli = new \Redis(); if($this->connect_type == FSOFConstants::FSOF_SERVICE_REDIS_CONNECT_TYPE_TCP) { $node = $this->hosts[$rand_num]; $ret = $redis_cli->connect($node[0],$node[1],$this->connect_timeout); $redis_cli->setOption(\Redis::OPT_READ_TIMEOUT, $this->read_timeout); $rand_num = ($rand_num + 1)%$hosts_count; if (!$ret) { $this->logger->warn("connect redis failed[{$node[0]}:{$node[1]}]"); } }else{ $ret = $redis_cli->connect("/var/fsof/redis.sock",-1,FSOFConstants::FSOF_SERVICE_REDIS_PORT,$this->connect_timeout); } if($ret) { break; } }catch (\Exception $e){ $this->logger->error('connect redis excepiton:'.$e->getMessage().', errno:' . $e->getCode()); } }while($retry-- > 0); if($ret) { $this->m_redis = $redis_cli; } else { $this->logger->error('connect redis failed:|errno:' . $redis_cli->getLastError()); throw new \Exception("连接redis异常"); } } return $this->m_redis; } public function getProviderInfo($key) { return $this->getlist($key); } public function get($key) { if (!empty($key) && isset($this->m_redis)) { return $this->m_redis->get($key); } else { return NULL; } } public function getlRange($key) { if (!empty($key) && isset($this->m_redis)) { return $this->m_redis->lRange($key, 0, -1); } else { $this->logger->warn('not object of redis:'.$key); return NULL; } } public function getlist($key) { if (!empty($key) && isset($this->m_redis)) { try{ return $this->getlRange($key); }catch (\Exception $e){ $this->logger->warn('redis current connect excepiton'.' |errcode:'.$e->getCode().' |errmsg:'.$e->getMessage()); $this->close(); //重试一次防止连接成功后,连接断开 $this->get_redis(); return $this->getlRange($key); } } else { return null; } } public function set($key, $value) { if (!empty($key) && isset($this->m_redis)) { return $this->m_redis->set($key, $value); } else { return null; } } /** * Description: 关闭redis连接 */ public function close() { try { if (isset($this->m_redis)) { $this->m_redis->close(); unset($this->m_redis); } } catch (\Exception $e) { unset($this->m_redis); $this->logger->error('close redis error:'.$e->getMessage(),$e); } } public function __destruct() { $this->close(); } }