CacheRedis.php 6.86 KB
<?php
/**
 * Created by PhpStorm.
 * User: Zip
 * Date: 14/11/23
 * Time: 上午1:39
 */

namespace Hood\Cache;

use \Redis as Redis;
use Hood\Core\Root;
use Hood\Debug\DebugException;

class CacheRedis extends Root implements CacheInterface
{
    private $redisInstances = array();

    private $section = 'redis';

    private $node = 'servers';

    private $childNodes = 'hosts';

    private $persistentIDs = array();

    private $tagName = '';

    private $prefix = '';

    private $persistentID = 'hood.cache';

    private $port = 6379;


    /**
     *
     * Enter description here ...
     * @var Redis
     */
    private $redis;

    private $timeout = 2.5;

    public function __construct($prefix = '', $persistentID = 'hood.cache')
    {
        parent::__construct();

        $this->prefix = $prefix;
        $this->persistentIDs[] = $this->persistentID = $persistentID;

    }


    /**
     * 设置共享连接ID
     * @param $persistentID
     * @return $this
     */
    public function setPersistentID($persistentID)
    {
        $this->persistentID = $persistentID;
        return $this;
    }


    /**
     * @return Redis
     * @throws DebugException
     */
    final private function init()
    {
        if (isset($this->redisInstances[$this->persistentID])) {
            $redis = $this->redisInstances[$this->persistentID];
        } else {
            $redis = new \Redis();

            $server = $this->getServerHost('cache');
            $_serverHosts = $server->getServerConfig($this->section, $this->node);
            if (empty($_serverHosts)) {
                throw new DebugException('redis node :' . $this->node . ' is null');
            }
            if (!isset($_serverHosts[$this->childNodes]) || empty($_serverHosts[$this->childNodes])) {
                throw new DebugException('Redis Host:' . $this->childNodes . ' is Null.');
            }

            $allServerAndPort = $this->_makeHosts($_serverHosts[$this->childNodes]);
            $serverAndPort = $allServerAndPort[rand(0, count($allServerAndPort) - 1)];
            $host = $serverAndPort[0];
            if (isset($serverAndPort[1]) && !empty($serverAndPort[1])) {
                $this->port = $serverAndPort[1];
            }
            try {
                $redis->connect($host, $this->port, $this->timeout);
            } catch (\RedisException $e) {
                throw new DebugException('redis connetc error:' . $host . ':' . $this->port . ' ' . $e->getMessage());
            }
            $this->redisInstances[$this->persistentID] = $redis;
        }
        return $redis;
    }


    /**
     * 设置子节点
     * @param $childNode
     * @return $this
     */
    public function setChildNodes($childNode)
    {
        $this->childNodes = $childNode;
        return $this;
    }


    /**
     * 设置redis配置的块
     * @param $section
     * @return $this
     */
    public function setSection($section)
    {
        $this->section = $section;
        return $this;
    }

    /**
     * 设置redis配置的块节点
     * @param $node
     * @return $this
     */
    public function setNode($node = null)
    {
        if ($node != null) $this->node = $node;
        return $this;
    }

    /**
     * 组织host
     * @param array $hosts
     * @return array
     */
    private function _makeHosts($hosts)
    {
        $servers = explode(',', $hosts);
        $_server = array();
        foreach ($servers as $val) {
            $_server[] = explode(':', $val);
        }
        return $_server;
    }


    /**
     *
     * 返回key所关联的字符串值,如果key不存在则返回特殊值nil。
     * @param String $key
     * @return Mixed or nil
     */
    public function get($key)
    {
        return $this->init()->get((string)$key);
    }

    /**
     * 设置key-value并设置过期时间
     * @param string $key
     * @param string $val
     * @param int $timeout 过期时间,单位:秒
     * @return bool
     * @throws DebugException
     */
    public function set($key, $val, $timeout = 0)
    {
        return $this->init()->set((string)$key, $val, $timeout);
    }

    /**
     *
     * @param $key
     * @param $ttl
     * @param $value
     * @return bool
     * @throws DebugException
     * @example $redis->setex('key', 3600, 'value');
     */
    public function setex($key, $ttl, $value)
    {
        return $this->init()->setex($key, $ttl, $value);
    }


    /**
     *
     * 选择数据库
     * @param int $db
     * @return bool
     */
    public function select($db = 9)
    {
        return $this->init()->select((int)$db);
    }


    /**
     * 增量
     * @param string $key
     * @param string $value
     * @throws DebugException
     */
    public function increment($key, $value = 1)
    {
        return $this->init()->incrBy((string)$key, (int)$value);
    }

    /**
     * 减量
     * @param string $key
     * @param int $value
     * @throws DebugException
     */
    public function decrement($key, $value = 1)
    {
        return $this->init()->decrBy((string)$key, (int)$value);
    }


    /**
     * 删除
     * @param $key
     * @return int
     * @throws DebugException
     */
    public function delete($key)
    {
        return $this->init()->del((string)$key);
    }


    public function add($key, $value, $minutes)
    {

    }


    public function tag($tagName)
    {

    }


    /**
     * 向list左压入
     * @param string $key
     * @param string $value
     * @throws DebugException
     */
    public function lpush($key, $value)
    {
        return $this->init()->lPush((string)$key, $value);
    }

    /**
     * 从list左弹出
     * @param string $key
     * @throws DebugException
     */
    public function lpop($key)
    {
        return $this->init()->lPop((string)$key);
    }


    /**
     * 向list右压入
     * @param string $key
     * @param string $value
     * @throws DebugException
     */
    public function rpush($key, $value)
    {
        return $this->init()->rPush((string)$key, $value);
    }

    /**
     * 从list右弹出
     * @param string $key
     * @throws DebugException
     */
    public function rpop($key)
    {
        return $this->init()->rPop((string)$key);
    }


    /**
     * 检查一个key是否存在
     * @param string $key
     * @return int
     */
    public function exists($key)
    {
        return $this->init()->exists((string)$key);
    }

    /**
     * 设置过期时间
     * @param string $key
     * @param int $second
     * @return int
     */
    public function expire($key, $second)
    {
        return $this->init()->expire((string)$key, (int)$second);
    }


    /**
     * 获取多个,返回数组按传入参数的顺序,不存在的,返回false
     * @return array
     */
    public function mget()
    {
        $keys = func_get_args();
        if (empty($keys)) {
            return array();
        }
        return $this->init()->mGet($keys);
    }

}