Yii框架中内置好几个缓存类,其中有memcache的类,但是没有redis缓存类,由于项目中需要做主从架构,所以扩展了一下:

/**
* FileName:RedisCluster
* 配置说明
* 配置为1主多从 或者 1个独立的服务器
* 写往主的里面写
* 读是从从的里面读
* 'class'=>'RedisCache',
* 'servers'=>array(
* array(
* 'host'=>'IP1',
* 'port'=>'6380',
* 'master'=>true //主机
* ),
* array(
* 'host'=>'IP2',
* 'port'=>'6381'
* )
*
* 单独
* 'class'=>'RedisCache',
* 'servers'=>array(
* array(
* 'host'=>'IP1',
* 'port'=>'6380',
* ), * @author zhonghailin
* @version v1.0
* @since v1.0
* @Date 2015-3-10 下午4:57:02
*/
class ERedisCache extends CCache{ // 是否使用 M/S 的读写集群方案
private $_isUseCluster = false; // Slave 句柄标记
private $_sn = 0; // 服务器连接句柄
private $_linkHandle = array(
'master'=>null,// 只支持一台 Master
'slave'=>array(),// 可以有多台 Slave
);
//配置文件
private $_servers=array();
/**
* 构造函数
*
* @param boolean $isUseCluster 是否采用 M/S 方案
*/
/*
* 初始化
*/
public function init()
{
$this->keyPrefix = "";
parent::init();
if(is_array($this->_servers)){
foreach($this->_servers as $servers){
if($servers->master){
$this->_isUseCluster = true;//如果设置了主服务器那么就是1主多从
$this->connect($servers,true);
}else{
$this->connect($servers);
}
}
}
} /**
* @return array list of memcache server configurations. Each element is a {@link CMemCacheServerConfiguration}.
*/
public function getServers()
{
return $this->_servers;
} /**
* @param array $config list of memcache server configurations. Each element must be an array
* with the following keys: host, port, persistent, weight, timeout, retryInterval, status.
* @see http://www.php.net/manual/en/function.Memcache-addServer.php
*/
public function setServers($config)
{
foreach($config as $c)
$this->_servers[]=new CRedisServerConfiguration($c);
}
/**
* 连接服务器,注意:这里使用长连接,提高效率,但不会自动关闭
*
* @param array $config Redis服务器配置
* @param boolean $isMaster 当前添加的服务器是否为 Master 服务器
* @return boolean
*/
public function connect($config, $isMaster=false){
// 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 2:
if(!empty( $this->_linkHandle['master'])){
$this->_linkHandle['master']->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 setValue($key, $value, $expire=0){
// 永不超时
if($expire == 0){
if($this->_isUseCluster){
$ret = $this->getRedis()->set($key, $value);
}else{
$ret = $this->getRedis(false)->set($key, $value);
}
}else{
if($this->_isUseCluster){
$ret = $this->getRedis()->setex($key, $expire, $value);
}else{
$ret = $this->getRedis(false)->setex($key, $expire, $value);
}
}
return $ret;
} /**
* 读缓存
*
* @param string $key 缓存KEY,支持一次取多个 $key = array('key1','key2')
* @return string || boolean 失败返回 false, 成功返回字符串
*/
public function getValue($key){
// 是否一次取多个值
$func = is_array($key) ? 'mGet' : 'get';
// 使用了 M/S
return $this->_getSlaveRedis()->{$func}($key);
} /**
* 条件形式设置缓存,如果 key 不存时就设置,存在时设置失败
*
* @param string $key 缓存KEY
* @param string $value 缓存值
* @return boolean
*/
public function setnx($key, $value){
if($this->_isUseCluster){
return $this->getRedis()->setnx($key, $value);
}else{
return $this->getRedis(false)->setnx($key, $value);
} } /**
* 删除缓存
*
* @param string || array $key 缓存KEY,支持单个健:"key1" 或多个健:array('key1','key2')
* @return int 删除的健的数量
*/
public function remove($key){
if($this->_isUseCluster){
return $this->getRedis()->delete($key);
}else{
return $this->getRedis(false)->delete($key);
}
} /* (non-PHPdoc)
* @see BaseCache::delete()
*/
public function deleteValue($key){
if($this->_isUseCluster){
return $this->getRedis()->delete($key);
}else{
return $this->getRedis(false)->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(){
if(!empty( $this->_linkHandle['master'])){
$this->_linkHandle['master']->flushDB();
}
for($i=0; $i<$this->_sn; ++$i){
$this->_linkHandle['slave'][$i]->flushDB();
}
return true;
} /* =================== 以下私有方法 =================== */ /**
* 随机 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 class CRedisServerConfiguration extends CComponent
{
/**
* @var string memcache server hostname or IP address
*/
public $host;
/**
* @var integer memcache server port
*/
public $port=11211; public $master = false;
/**
* Constructor.
* @param array $config list of memcache server configurations.
* @throws CException if the configuration is not an array
*/
public function __construct($config)
{
if(is_array($config))
{
foreach($config as $key=>$value)
$this->$key=$value;
if($this->host===null)
throw new CException(Yii::t('yii','CMemCache server configuration must have "host" value.'));
}
else
throw new CException(Yii::t('yii','CMemCache server configuration must be an array.'));
}
}

Yii框架下使用redis做缓存,读写分离的更多相关文章

  1. yii框架下使用redis

    1 首先获取到 yii2-redis-master.zip 压缩包 下载地址https://github.com/yiisoft/yii2-redis/archive/master.zip 2 把下载 ...

  2. Yii框架 多数据库、主从、读写分离

    Yii是可以在配置文件里声明多个数据库连接,然后通过Yii::app()->db1,Yii::app()->db2...来访问它们,并且也实现了更高级(自动)的主从数据库功能. 最近因为一 ...

  3. spring+redis的集成,redis做缓存

    1.前言 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.我们都知道,在日常的应用中,数据库瓶颈是最容易出现的 ...

  4. SpringBoot之Mybatis操作中使用Redis做缓存

    上一博客学习了SpringBoot集成Redis,今天这篇博客学习下Mybatis操作中使用Redis做缓存.这里其实主要学习几个注解:@CachePut.@Cacheable.@CacheEvict ...

  5. 项目总结10:通过反射解决springboot环境下从redis取缓存进行转换时出现ClassCastException异常问题

    通过反射解决springboot环境下从redis取缓存进行转换时出现ClassCastException异常问题 关键字 springboot热部署  ClassCastException异常 反射 ...

  6. spring-boot集成mybatis,用redis做缓存

    网上有很多例子了,执行源码起码有3个,都是各种各样的小问题. 现在做了个小demo,实现spring-boot 用redis做缓存的实例,简单记录下思路,分享下源码. 缓存的实现,分担了数据库的压力, ...

  7. 如何用redis做缓存

    redis缓存 在互联网应用中经常需要用redis来缓存热点数据. redis数据在内存,可以保证数据读取的高效,接近每秒数十万次的吞吐量 减少下层持久层数据库读取压力,像mongodb,每秒近千次读 ...

  8. django使用redis做缓存

    Django 使用 Redis 做缓存 django中应用redis:pip3 install django-redis - 配置 CACHES = { "default": { ...

  9. Spring Boot 2整合Redis做缓存

    既然是要用Redis做缓存,自然少不了安装了.但是本文主要讲Spring Boot与Redis整合.安装教程请另行百度! 1.首先是我们的Redis配置类 package com.tyc; impor ...

随机推荐

  1. 学习笔记之SQL Programming DB2

    http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp If you intend to update a column or ...

  2. eclipse创建多模块maven工程小结

    创建maven工程步骤 1 新建一个maven工程,如下图所示: 2 选择项目名称(或项目目录),如下图所示: 3 填写maven工程相关信息,注意父maven工程的packing方式是pom,如下图 ...

  3. 如何查找局域网的外网ip

    方法一:一个简单的方法 用你电脑打开www.ip138.com 就可以看到自己的公网IP地址 方法二:如果一定要从路由器里面看 那就打开路由的配置页面 一般在系统状态里面 会有个WAN口IP 那就是你 ...

  4. STC89C52单片机内部EEPROM驱动

    STC89C52单片机自身带有4K的存储空间,分为8个扇区,每个扇区512字节,第一扇区起始地址为:0x2000, 结束地址为:21FF, 第八扇区起始地址为0x2E00,结束地址是2FFF #inc ...

  5. 如何去除掉inline-block元素之间的默认间距

    前几天写一个页面 div{width:900px;} div li{ display:inline-block; width:300px;} <ul> <li></li& ...

  6. UNIX V6内核源码剖析——unix v6 全貌

    1. UNIX V6 运行硬件环境——PDP-11/40 PDP-11/40指令和数据都是以16比特为单位.对它而言,一个字的宽度为16比特. PDP-11/40以及周边设备的寄存器被映射到内存最高位 ...

  7. c语言面试题之sizeof

    c语言面试题之sizeof */--> c语言面试题之sizeof Table of Contents 1. sizeof 1 sizeof sizeof是c语言中判断数据类型或者表达式的长度符 ...

  8. 动态上传多个文件(asp)

    CreateElements.html <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  9. MySQL与NoSQL——SQL与NoSQL的融合

    来源:http://www.cnblogs.com/sunli/archive/2011/05/11/mysql-nosql.html 写这一篇内容的原因是MySQL5.6.2突然推出了memcach ...

  10. 字符串 前篇 ---- sizeof()操作符和strlen()库函数

    本文不是研究sizeof(), strlen() 的深奥定义和原理,我们不会在理论上太过钻牛角尖.希望读这篇文章的你,也不要太过抠概念(不要拘泥于语法).我们只做 实用意义 的介绍和讨论. 在介绍字符 ...