PHP Redis 集群封装类

<?php

/**

 * Redis 操作,支持 Master/Slave 的负载集群

 *

 * @author V哥

 */

class RedisCluster{

 

    // 是否使用 M/S 的读写集群方案

    private $_iSUSECluster = false;

 

    // Slave 句柄标记

    private $_sn = 0;

 

    // 服务器连接句柄

    private $_linkHandle = array(

        ‘master‘=>null,// 只支持一台 Master

        ‘slave‘=>array(),// 可以有多台 Slave

    );

 

    /**

     * 构造函数

     *

     * @param boolean $isUseCluster 是否采用 M/S 方案

     */

    public function __construct($isUseCluster=false){

        $this->_isUseCluster = $isUseCluster;

    }

 

    /**

     * 连接服务器,注意:这里使用长连接,提高效率,但不会自动关闭

     *

     * @param array $config Redis服务器配置

     * @param boolean $isMaster 当前添加的服务器是否为 Master 服务器

     * @return boolean

     */

    public function connect($config=array(‘host‘=>‘127.0.0.1‘,‘port‘=>6379), $isMaster=true){

        // default port

        if(!isset($config[‘port‘])){

            $config[‘port‘] = 6379;

        }

        // 设置 Master 连接

        if($isMaster){

            $this->_linkHandle[‘master‘] = new Redis();

            $ret = $this->_linkHandle[‘master‘]->pconnect($config[‘host‘],$config[‘port‘]);

        }else{

            // 多个 Slave 连接

            $this->_linkHandle[‘slave‘][$this->_sn] = new Redis();

            $ret = $this->_linkHandle[‘slave‘][$this->_sn]->pconnect($config[‘host‘],$config[‘port‘]);

            ++$this->_sn;

        }

        return $ret;

    }

 

    /**

     * 关闭连接

     *

     * @param int $flag 关闭选择 0:关闭 Master 1:关闭 Slave 2:关闭所有

     * @return boolean

     */

    public function close($flag=2){

        switch($flag){

            // 关闭 Master

            case 0:

                $this->getRedis()->close();

            break;

            // 关闭 Slave

            case 1:

                for($i=0; $i<$this->_sn; ++$i){

                    $this->_linkHandle[‘slave‘][$i]->close();

                }

            break;

            // 关闭所有

            case 1:

                $this->getRedis()->close();

                for($i=0; $i<$this->_sn; ++$i){

                    $this->_linkHandle[‘slave‘][$i]->close();

                }

            break;

        }

        return true;

    }

 

    /**

     * 得到 Redis 原始对象可以有更多的操作

     *

     * @param boolean $isMaster 返回服务器的类型 true:返回Master false:返回Slave

     * @param boolean $slaveOne 返回的Slave选择 true:负载均衡随机返回一个Slave选择 false:返回所有的Slave选择

     * @return redis object

     */

    public function getRedis($isMaster=true,$slaveOne=true){

        // 只返回 Master

        if($isMaster){

            return $this->_linkHandle[‘master‘];

        }else{

            return $slaveOne ? $this->_getSlaveRedis() : $this->_linkHandle[‘slave‘];

        }

    }

 

    /**

     * 写缓存

     *

     * @param string $key 组存KEY

     * @param string $value 缓存值

     * @param int $expire 过期时间, 0:表示无过期时间

     */

    public function set($key, $value, $expire=0){

        // 永不超时

        if($expire == 0){

            $ret = $this->getRedis()->set($key, $value);

        }else{

            $ret = $this->getRedis()->setex($key, $expire, $value);

        }

        return $ret;

    }

 

    /**

     * 读缓存

     *

     * @param string $key 缓存KEY,支持一次取多个 $key = array(‘key1‘,‘key2‘)

     * @return string || boolean  失败返回 false, 成功返回字符串

     */

    public function get($key){

        // 是否一次取多个值

        $func = is_array($key) ? ‘mGet‘ : ‘get‘;

        // 没有使用M/S

        if(! $this->_isUseCluster){

            return $this->getRedis()->{$func}($key);

        }

        // 使用了 M/S

        return $this->_getSlaveRedis()->{$func}($key);

    }

 

    /**

     * 条件形式设置缓存,如果 key 不存时就设置,存在时设置失败

     *

     * @param string $key 缓存KEY

     * @param string $value 缓存值

     * @return boolean

     */

    public function setnx($key, $value){

        return $this->getRedis()->setnx($key, $value);

    }

 

    /**

     * 删除缓存

     *

     * @param string || array $key 缓存KEY,支持单个健:"key1" 或多个健:array(‘key1‘,‘key2‘)

     * @return int 删除的健的数量

     */

    public function remove($key){

        // $key => "key1" || array(‘key1‘,‘key2‘)

        return $this->getRedis()->delete($key);

    }

 

    /**

     * 值加加操作,类似 ++$i ,如果 key 不存在时自动设置为 0 后进行加加操作

     *

     * @param string $key 缓存KEY

     * @param int $default 操作时的默认值

     * @return int 操作后的值

     */

    public function incr($key,$default=1){

        if($default == 1){

            return $this->getRedis()->incr($key);

        }else{

            return $this->getRedis()->incrBy($key, $default);

        }

    }

 

    /**

     * 值减减操作,类似 --$i ,如果 key 不存在时自动设置为 0 后进行减减操作

     *

     * @param string $key 缓存KEY

     * @param int $default 操作时的默认值

     * @return int 操作后的值

     */

    public function decr($key,$default=1){

        if($default == 1){

            return $this->getRedis()->decr($key);

        }else{

            return $this->getRedis()->decrBy($key, $default);

        }

    }

 

    /**

     * 添空当前数据库

     *

     * @return boolean

     */

    public function clear(){

        return $this->getRedis()->flushDB();

    }

 

    /* =================== 以下私有方法 =================== */

 

    /**

     * 随机 HASH 得到 Redis Slave 服务器句柄

     *

     * @return redis object

     */

    private function _getSlaveRedis(){

        // 就一台 Slave 机直接返回

        if($this->_sn <= 1){

            return $this->_linkHandle[‘slave‘][0];

        }

        // 随机 Hash 得到 Slave 的句柄

        $hash = $this->_hashId(mt_rand(), $this->_sn);

        return $this->_linkHandle[‘slave‘][$hash];

    }

 

    /**

     * 根据ID得到 hash 后 0~m-1 之间的值

     *

     * @param string $id

     * @param int $m

     * @return int

     */

    private function _hashId($id,$m=10)

    {

        //把字符串K转换为 0~m-1 之间的一个值作为对应记录的散列地址

        $k = md5($id);

        $l = strlen($k);

        $b = bin2hex($k);

        $h = 0;

        for($i=0;$i<$l;$i++)

        {

            //相加模式HASH

            $h += substr($b,$i*2,2);

        }

        $hash = ($h*1)%$m;

        return $hash;

    }

 

}// End Class

 

// ================= TEST DEMO =================

 

// 只有一台 Redis 的应用

$redis = new RedisCluster();

$redis->connect(array(‘host‘=>‘127.0.0.1‘,‘port‘=>6379));

$redis->set(‘id‘,35);

var_dump($redis->get(‘id‘));

 

// 有一台 Master 和 多台Slave 的集群应用

$redis = new RedisCluster(true);

$redis->connect(array(‘host‘=>‘127.0.0.1‘,‘port‘=>6379), true);// master

$redis->connect(array(‘host‘=>‘127.0.0.1‘,‘port‘=>63791), false);// slave 1

$redis->connect(array(‘host‘=>‘127.0.0.1‘,‘port‘=>63792), false);// slave 2

$redis->set(‘id‘,100);

for($i=1; $i<=100; ++$i){

    var_dump($redis->get(‘id‘)).PHP_EOL;

}

 

// phpRedis 扩展的更多高级操作

$redis = new RedisCluster();

$redis->connect(array(‘host‘=>‘127.0.0.1‘,‘port‘=>6379));

$ret = $redis->getRedis()->ping();// phpRedis 原始API

var_dump($ret);

时间: 2024-08-26 09:13:28

PHP Redis 集群封装类的相关文章

redis 集群

redis 集群 redis集群是redis提供分布式数据库方案, 集群通过分片(Sharding)来进行数据共享,并提供复制和故障转移功能. 节点 redis集群通常由多个节点(node)组成,在开始每个node 都是相互独立的. 要组建成真正可工作的集群,我们必须将各个独立的节点连接起来,构成一个包含多个节点的集群. 命令 cluster meet <ip> <port> 向一个node 发送命令 cluster meet,让节点与ip/port所指定的节点 进行握手(hand

Redis集群的高可用测试(含Jedis客户端的使用)

Redis集群的使用测试(Jedis客户端的使用) 1.  Jedis客户端建议升级到最新版(当前为2.7.3),这样对3.0.x集群有比较好的支持. https://github.com/xetorthio/jedis http://mvnrepository.com/artifact/redis.clients/jedis 2.  直接在Java代码中链接Redis集群: // 数据库链接池配置 JedisPoolConfig config = new JedisPoolConfig();

redis集群

redis集群 redis锁 1.Redis集群是一个提供在多个redis节点间共熟数据的程序集. 2.redis集群的数据分片(1)Redis没有使用一致性hash而是引入hash槽的概念.(2)Redis集群共有16384个hash槽(不管redis有几台机器,整个集群一共有16384个hash槽).每个key经过CRC16校验后,对16384取余来决定放到哪个hash槽.(3)比如一个集群有A.B.C.3台机器,那么 节点A,包括0到5500号hash槽 节点B,包含 5501到11000

剑指架构师系列-Redis集群部署

初步搭建Redis集群 克隆已经安装Redis的虚拟机,我们使用这两个虚拟机中的Redis来搭建集群. master:192.168.2.129 端口:7001 slave:192.168.2.132 端口:7002 sentinel:192.168.2.129 端口:26379 来说一下这个sentinel,sentinel是一个管理redis实例的工具,它可以实现对redis的监控.通知.自动故障转移.sentinel不断的检测redis实例是否可以正常工作,通过API向其他程序报告redi

Redis集群错误

部署Redis集群时出现如下错误: >>> Creating cluster>>> Performing hash slots allocation on 9 nodes...Using 4 masters:192.168.247.40:7000192.168.247.40:7001192.168.247.40:7002192.168.247.40:7003Adding replica 192.168.247.40:7004 to 192.168.247.40:7000

redis集群、单击版本与spring整合步骤

1.搭建集群,关闭虚拟机防火墙,或者iptables参数,允许redis集群端口通过 service iptables stop 或者 vim /etc/sysconfig/iptables 2.测试集群(不整合spring) @Test public void testJedisCluster(){ HashSet<HostAndPort> nodes = new HashSet<HostAndPort>(); nodes.add(new HostAndPort("19

redis 集群配置实战

最近研究Redis-cluster,正好搭建了一个环境,遇到了很多坑,系统的总结下,等到redis3 release出来后,换掉memCache 集群. 一:关于redis cluster 1:redis cluster的现状 reids-cluster计划在redis3.0中推出,可以看作者antirez的声明:http://antirez.com/news/49 (ps:跳票了好久,今年貌似加快速度了),目前的最新版本是redis3 beta2(2.9.51). 作者的目标:Redis Cl

redis集群原理

redis是单线程,但是一般的作为缓存使用的话,redis足够了,因为它的读写速度太快了.   官方的一个简单测试: 测试完成了50个并发执行100000个请求. 设置和获取的值是一个256字节字符串. 结果:读的速度是110000次/s,写的速度是81000次/s 在这么快的读写速度下,对于一般程序来说足够用了,但是对于访问量特别大的网站来说,还是稍有不足.那么,如何提升redis的性能呢?看标题就知道了,搭建集群. 3.0版本之前 3.0版本之前的redis是不支持集群的,我们的徐子睿老师说

Windows下搭建Redis集群

Redis集群:运行多个Redis实例,然后通过特定的工具,将这些实例以某种关系连接起来,形成一个Redis网络. 详细的内容可以阅读:Redis 集群教程 里面会详细介绍Redis集群的设计思想和内部结构,以及如何搭建Redis集群等. 本文主要讲述如何在Windows系统下快速搭建Redis集群: 1.下载Redis 其GitHub连接如下:https://github.com/MSOpenTech/redis/releases/ Redis提供msi和zip格式的下载文件,这里下载zip格