转http://www.cnblogs.com/jackluo/p/3410192.html

<?php

/**
* RedisCluster 群redius操作类
*
* //创建连接
* $rc = new RedisCluster();
* $rc->connect(array("host" => "127.0.0.1", "port" => 6379)); //php客户端设置的ip及端口
* //存储值
* $rc->set($key,$value);
* $rc->set($array);
* $rc->setnx($key,$value);//只创不更
* $rc->setnx($array);//只创不更
* //获取值
* $rc->get($key);
* $rc->get($array);
* //删除
* $rc->delete($key);
* $rc->delete($array);
* //删除所有
* $rc->deleteAll();
* //+1或者其他
* $rc->incr($key[,$othervar]);
* //-1或者其他
* $rc->decr($key[,$othervar]);
* //关闭连接 0.主服务器,1.从服务器,2.全部
* $rc->close(2);
*
* hujiande 297538600@qq.com
* @date 2014.8.15
*/
class RedisCluster extends NoRewindIterator { // 是否使用 M/S 的读写集群方案
private $_isUseCluster = false;
// Slave 句柄标记
private $_sn = 0;
// 服务器连接句柄
private $_linkHandle = array(
'master' => null, // 只支持一台 Master
'slave' => array(), // 可以有多台 Slave
); /**
* 构造函数
*
* @access $rc = new RedisCluster($isUseCluster=false);
* @param boolean $isUseCluster 是否采用 M/S 方案
*/
public function __construct($isUseCluster = false) {
$this->_isUseCluster = $isUseCluster;
} /**
* 连接服务器,注意:这里使用长连接,提高效率,但不会自动关闭
*
* @access $rc->connect($config=array('host'=>'127.0.0.1','port'=>6379), $isMaster=true);
* @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;
} /**
* 关闭连接
*
* @access $rc->connect($flag=2);
* @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 原始对象
*
* @access $rc->getRedis(true, true);
* @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'];
}
} /**
* 写缓存
*
* @access $rc->set($key, $value, $expire);//存储单个键值
* @access $rc->set($array, $expire);//存储多个键值
* @param string $key 组存KEY
* @param string $value 缓存值
* @param int $expire 过期时间,0:表示无过期时间 单位m秒
* @param boolean $is_nx 是否只创建不更新
*/
public function set($key, $value = '', $expire = 0) {
//存储多个键值
if (is_array($key)) {
$array = $key;
$expire = (int) $value; // 永不超时
if ($expire == 0) {
$ret = $this->getRedis()->mset($array);
}
else {
$ret = true; foreach ($array as $key1 => $value1) {
$ret = $this->set($key1, $value1, $expire, $is_nx) && $ret;
} } }
//存储单个键值
else {
// 永不超时
if ($expire == 0) {
$ret = $this->getRedis()->set($key, $value);
}
else {
$ret = $this->getRedis()->setex($key, $expire, $value);
} } return $ret;
} /**
* 只创建$key的值,不更新已存在的$key值
*
* @access $rc->setnx($not_exist_key, $value);//不更新已存在的$key值
* @access $rc->setnx($array);//不更新已存在的$key值
* @param string $not_exist_key 缓存KEY
* @param string $value 缓存值
* @return boolean
*/
public function setnx($not_exist_key, $value = '') { if (is_array($not_exist_key)) { return $this->getRedis()->msetnx($not_exist_key);
} else { return $this->getRedis()->setnx($not_exist_key, $value);
} } /**
* 读缓存
*
* @access $rc->get($key);
* @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);
} /**
* 删除缓存
*
* @access $rc->delete($key);
* @param string || array $key 缓存KEY,支持单个健:"key1" 或多个健:array('key1','key2')
* @return int 删除的健的数量
*/
public function delete($key) {
return $this->getRedis()->delete($key);
} /**
* 清空当前数据库
*
* @access $rc->deleteAll();
* @return boolean
*/
public function deleteAll() {
return $this->getRedis()->flushDB();
} /**
* 值加加操作,类似 ++$i ,如果 key 不存在时自动设置为 0 后进行加加操作
*
* @access $rc->incr($key, $default=1);
* @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 后进行减减操作
*
* @access $rc->decr($key, $default=1);
* @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);
}
} /* =================== 以下私有方法 =================== */ /**
* 随机 HASH 得到 Redis Slave 服务器句柄
* @access $this->_getSlaveRedis();
* @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 之间的值
* @access $this->_hashId($id, $m=10);
* @param string $id
* @param int $m
* @return int
*/
private function _hashId($id, $m = 10) {
//把字符串K转换为 0~m-1 之间的一个值作为对应记录的散列地址
$k = md5($id);
$md5_len = 32;
$b = bin2hex($k);
$h = 0;
for ($i = 0; $i < $md5_len; $i++) {
//相加模式HASH
$h += substr($b, $i * 2, 2);
}
$hash = ($h * 1) % $m;
return $hash;
} }

  

优化过的redis封装类的更多相关文章

  1. redis优化配置和redis.conf说明

    1. redis.conf 配置參数: #是否作为守护进程执行 daemonize yes #如以后台进程执行,则需指定一个pid,默觉得/var/run/redis.pid pidfile redi ...

  2. 写一个Redis封装类

    打算自己封装一个Redis操作类,方便使用,且有一定log记录.Redis的封装思路:基于Redis类进一步封装 一般属性 单例 (配置参数从配置文件中读取还是写死?考虑多配置之间切换) 常规操作根据 ...

  3. redis优化配置和redis.conf说明(转)

    1. redis.conf 配置参数: #是否作为守护进程运行 daemonize yes #如以后台进程运行,则需指定一个pid,默认为/var/run/redis.pid pidfile redi ...

  4. asp.net性能优化之使用Redis缓存(入门)

    1:使用Redis缓存的优化思路 redis的使用场景很多,仅说下本人所用的一个场景: 1.1对于大量的数据读取,为了缓解数据库的压力将一些不经常变化的而又读取频繁的数据存入redis缓存 大致思路如 ...

  5. 详谈redis优化配置和redis.conf

    1. Redis.conf 配置参数: #是否作为守护进程运行 daemonize yes #如以后台进程运行,则需指定一个pid,默认为/var/run/redis.pid pidfile redi ...

  6. 【转载】redis优化配置和redis.conf说明

    转载地址:http://blog.csdn.net/luozhonghua2014/article/details/40568707?utm_source=tuicool&utm_medium ...

  7. 业务层面和运维层面优化你的Redis

    业务层面 key的长度尽量要短,在数据量非常大时,过长的key名会占用更多的内存; 一定避免存储过大的数据(大value),过大的数据在分配内存和释放内存时耗时严重,会阻塞主线程; Redis 4.0 ...

  8. StackExchange.Redis 封装类

    using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; using ...

  9. Redis高级实践之————Redis短连接性能优化

    摘要: 对于Redis服务,通常我们推荐用户使用长连接来访问Redis,但是由于某些用户在连接池失效的时候还是会建立大量的短连接或者用户由于客户端限制还是只能使用短连接来访问Redis,而原生的Red ...

随机推荐

  1. java 输入输出 函数对象构造

    /*********************输入输出*******************/   //输入字符串 不包括最后的换行符'\n'     import java.io.BufferedRe ...

  2. mvc3.0 +linq 操作数据库中表的数据(ps:本人菜鸟刚学)

    1:添加控制器类文件HomeController.cs其代码如下: using System; using System.Collections.Generic; using System.Linq; ...

  3. Android中GridLayout与GridView区别

    GridLayout初步研究:可以这么说这个布局绝对是开发者的福音,它大大简化了对复杂布局的处理,包括性能提高不是一倍两倍.它与GridView是完全不同的概念, GridView是一种适配器布局,它 ...

  4. linux初学 :linux 常用命令(一)

    首先,是关机/重启命令,仅在虚拟机时使用,实际工作中用不到 reboot 一般不跟参数使用,输入指令即可重启 shutdown 一般需要跟参数,例: shutdown -r 延时多少分钟重启,一般使用 ...

  5. 百篇大计敬本年之系统篇《六》—— Ubuntu 16.04开启 root 超级用户

    Ubuntu 16.04系统在一开始安装完成时是无法切换到 root 用户的,普通用户需要使用 root 权限的时候通常需要在执行命令前加 "sudo",需要经常使用root权限的 ...

  6. JavaScript实现XML与JSON互转代码(转载)

    下面来分享一个关于JavaScript实现XML与JSON互转例子,这里面介绍了国外的三款xml转json的例子,希望这些例子能给你带来帮助. 最近在开发在线XML编辑器,打算使用JSON做为中间格式 ...

  7. [转]使用 HTML5 索引型数据库的待办事项简要列表

    本文转自:http://www.html5rocks.com/zh/tutorials/indexeddb/todo/ <!DOCTYPE html><html>  <h ...

  8. Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序

    Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...

  9. date & dirname

    date 年:+%Y 月:+%m 日:+%d 时:+%H 或者 +%k 分:+%M 秒:+%S 周:+%w dirname 目录 获取目录的上级目录

  10. IT技术方案最佳实践方案的收集

    一.图片鉴别服务 1. 阿里云,腾讯云等公开的服务. 2. 图谱科技提供的API 二. 网络直播服务器 1. SRS2 开源服务器 (https://github.com/ossrs/srs/wiki ...