PHP Redis 集群封装类
<?php
/**
* Redis 操作,支持 Master/Slave 的负载集群
*
* @author V哥
*/
class
RedisCluster{
// 是否使用 M/S 的读写集群方案
// 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
);
PHP Redis 集群封装类的更多相关文章
- Redis集群案例与场景分析
1.背景 Redis的出现确实大大地提高系统大并发能力支撑的可能性,转眼间Redis的最新版本已经是3.X版本了,但我们的系统依然继续跑着2.8,并很好地支撑着我们当前每天5亿访问量的应用系统.想当年 ...
- Java Spring mvc 操作 Redis 及 Redis 集群
本文原创,转载请注明:http://www.cnblogs.com/fengzheng/p/5941953.html 关于 Redis 集群搭建可以参考我的另一篇文章 Redis集群搭建与简单使用 R ...
- Redis集群搭建与简单使用
介绍安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. 两台虚拟机都是 CentOS ,一台 ...
- window下使用Redis Cluster部署Redis集群
日常的项目很多时候都需要用到缓存.redis算是一个比较好的选择.一般情况下做一个主从就可以满足一些比较小的项目需要.在一些并发量比较大的项目可能就需要用到集群了,redis在Windows下做集群可 ...
- Redis集群~windows下搭建Sentinel环境及它对主从模式的实际意义
回到目录 关于redis-sentinel出现的原因 Redis集群的主从模式有个最大的弊端,就是当主master挂了之前,它的slave从服务器无法提升为主,而在redis-sentinel出现之后 ...
- [个人翻译]Redis 集群教程(中)
上一篇:http://www.cnblogs.com/li-peng/p/6143709.html 官方原文地址:https://redis.io/topics/cluster-tutorial 水 ...
- [个人翻译]Redis 集群教程(上)
官方原文地址:https://redis.io/topics/cluster-tutorial 水平有限,如果您在阅读过程中发现有翻译的不合理的地方,请留言,我会尽快修改,谢谢. 这是 ...
- Redis集群(九):Redis Sharding集群Redis节点主从切换后客户端自动重新连接
上文介绍了Redis Sharding集群的使用,点击阅读 本文介绍当某个Redis节点的Master节点发生问题,发生主从切换时,Jedis怎样自动重连新的Master节点 一.步骤如下: 1.配 ...
- Redis集群(八):Redis Sharding集群
一.Redis目前的集群方案主要有两种:Redis Sharding和Redis Cluster 1.Redis Sharding:3.0以前基本上使用分片实现集群,目前主流方案,客户端实现 2.Re ...
随机推荐
- HotSpot Builder Utility安装指南
系统需求硬件- 一台带有1个以太网卡的电脑(宿主机)- 一个无线路由器 软件- VirtualBox 4.1或更高的版本.下载网址:http://www.virtualbox.org/- 我们提供的最 ...
- Eclipse C/C++开发环境搭建
1 Eclipse的安装 到http://java.sun.com/j2se/1.5.0/download.jsp 下载JRE安装: 到http://eclipse.org下载Eclipse安装.(这 ...
- iOS 进阶 第九天(0408)
0408 makekeyAndVisible解释 一个程序可以有多个Window,但只有一个窗口能够成为主窗口.如图中所示,此时的window2是主窗口.主窗口用处大了.从iOS7开始无论是主窗口还是 ...
- Android之EditText
EditText 属性介绍: maxLength:设置最大输入字符数. hint:设置空白提示文字. textColorHint:设置空白提示文字的颜色. enabled:设置是否可编辑(可以获得焦点 ...
- 微软职位内部推荐-SDE2 (Windows - Power)
微软近期Open的职位: SDE2 (Windows - Power) Windows Partner Enablement team in Operating System Group is loo ...
- C++中使用心得
1.struct成员默认访问方式是public,而 class默认访问方式是private! 2.exit函数终止程序执行会调用析构函数 ,abort函数终止程序不会调用析构函数! 3.静态局部变量直 ...
- SpringMVC+redis整合
在网络上有一个很多人转载的springmvc+redis整合的案例,不过一直不完整,也是被各种人装来转去,现在基本将该框架搭建起来. package com.pudp.bae.base; import ...
- 典型的js页面
var myurl; var mydata; var postype = "POST"; var getype = "GET"; var jsontype = ...
- RabbitMQ学习(1):安装
1.安装 Erlang,官网:https://www.erlang.org/ 2.安装RabbitMQ服务器,rabbitMQ server,官网http://www.rabbitmq.com/ 注: ...
- EXT经验--查询EditorGridPanel的tbar的默认配置对象
前言:EXT的API可谓熟悉EXT的葵花宝典,会看API可谓对于配置EXT,学习EXT最重要的基本功,这点相对于学习轻量级的Easyui来说更加明显. 比如下面的一段代码:注:在Ext.grid.Ed ...