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 ...
随机推荐
- 从零开始学ios开发(六):IOS控件(3),Segmented Control、Switch
这次的学习还是基于上一个项目继续进行(你也可以新建一个项目)学习Segmented Control和Switch. Segmented Control Switch Segmented Control ...
- 收起虚拟键盘的各种方法 -- IOS
使用虚拟键盘来输入资讯,是 iOS 的重要互动方式之一,虚拟键盘通常会自动出现在可以编辑的 UITextField 或是 UITextView 的编辑事件中,叫出键盘固然容易,但是要把它收起来,可就没 ...
- 如何保持iOS上键盘出现时输入框不被覆盖
在 iOS5 上请求显示键盘时,系统从屏幕底部将键盘滑入上来,位于应用的内容之上. (墙内:http://mikixiyou.iteye.com/blog/1488302) 如果屏幕中的内容项目比较多 ...
- php中函数内使用static修饰变量
首先理解静态变量的区别,声明一个函数test() function num(){ $a = 0; echo $a; $a++; } num();num();num(); //输出000 functio ...
- 让CALayer的shadowPath跟随bounds一起做动画改变-b
在iOS开发中,我们经常需要给视图添加阴影效果,最简单的方法就是通过设置CALayer的shadowColor.shadowOpacity.shadowOffset和shadowRadius这几个属性 ...
- bitmap缩放时抗锯齿
bitmap在进行放大缩小的时候经常会出现边缘锯齿的情况,通常的解决办法是在Paint中加入抗锯齿, paint.setAntiAlias(true); 但是有时候发现这并没有起到抗锯齿的作用,这是可 ...
- DataTable.Compute 性能慢的问题
问题描述 工作中碰到一个dt.Compute("max(lineid)","")来取最大行号的情况,由于dt中数据大概有4000条,发现每次调用需要0.3秒的耗 ...
- Codeforces Round #360 (Div. 2) D. Remainders Game 中国剩余定理
题目链接: 题目 D. Remainders Game time limit per test 1 second memory limit per test 256 megabytes 问题描述 To ...
- javaScript基础之闭包
不管是Jquery还是EXTJS,现代的js框架中大量应用了js的一些特性,比如:匿名函数,闭包等等,导致源代码非常难以阅读. 不过要想真正的使用好前台的UI技术,还是需要去深入的理解这些概念. ...
- C# 数据结构--排序[上]
概述 看了几天的排序内容,现在和大家分享一些常见的排序方法. 啥是排序? 个人理解的排序:通过对数组中的值进行对比,交换位置最终得到一个有序的数组.排序分为内存排序和外部排序.本次分享排序方法都为内存 ...