thinkphp的redis主从分布式的单例模式
来源:互联网 发布:传媒大学网络教育 编辑:程序博客网 时间:2024/06/05 22:37
最近公司的项目越做越大,数据量越来越大,逐渐地要开始支持分布式的数据库,当然包括要缓存。经过了各种的讨论和认证,决定用redis服务器作为数据缓存的服务器,除了支持丰富的数据类型,string,list,hash,set ,sort set ,还有持久化的数据的功能。这一方面确实比memcache好很多。下面是我的整个测试过程(tp3.2以上)。
注意:首先要安装phpredis和配置好redis的主从复制,并且要启动各个redis的实例。
与tp自带的redis.class.php的缓存驱动不同,实现功能
1、可以实现主从分布,多个slave
2、master主要负责写,slave负责随机读
3、单例模式,一次实例化所有的redis,包括master,slave。不需要每操作一次redis,就连接redis一次,那样严重浪费资源。
4、自由拓展,可以根据自己的需要继续添加redis的API操作。
一、tp的redis配置
// REDIS配置'DATA_CACHE_TYPE' =>'Redis','DATA_REDIS_HOST' =>'localhost,localhost','DATA_REDIS_PORT' =>'6379,6380','DATA_CACHE_TIME' =>30,'DATA_CACHE_PREFIX' =>'redis_','DATA_PERSISTENT'=>true</span>默认第一个是master,其余的是slave。
二、redis的缓存驱动
<?php// +----------------------------------------------------------------------// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]// +----------------------------------------------------------------------// | Copyright (c) 2006-2013 http://thinkphp.cn All rights reserved.// +----------------------------------------------------------------------// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )// +----------------------------------------------------------------------// | Author: liu21st <liu21st@gmail.com>// +----------------------------------------------------------------------namespace Think\Cache\Driver;use Think\Cache;defined('THINK_PATH') or exit();/** * Redis缓存驱动 * 要求安装phpredis扩展:https://github.com/nicolasff/phpredis * @category Think * @package Cache * @subpackage Driver * @author huangzengbing */class Redisrw extends Cache {/***类对象实例数组*共有静态变量*@param mixed $_instance存放实例*/private static $_instance=array();/***每次实例的句柄*保护变量*/protected $handler;/***redis的配置*全局 静态变量*静态的方法里调用静态变量和静态方法只能用self,不能出现$this*/static $option=array();/***架构函数,必须设置为私有,防止外部new*实例化redis驱动的实例,寄一个socket**/private function __construct($host,$port,$auth) {if(!$this->handler) {$this->handler= new \Redis;} $func = self::$option['persistent'] ? 'pconnect' : 'connect'; if(self::$option['timeout'] === false) {$this->handler->$func($host,$port);}else {$this->handler->$func($host,$port,self::$option['timeout']);}// 认证if($auth){$this->handler->auth($auth);}}/***实例函数,单例入口*共有,静态函数*/public static function getInstance($options=array()) {// 判断是否存在redis扩展if ( !extension_loaded('redis') ) { E(L('_NOT_SUPPERT_').':redis'); } if(empty($options)) { $options = array ( 'host' => C('DATA_REDIS_HOST') ? C('DATA_REDIS_HOST') : '127.0.0.1', 'port' => C('DATA_REDIS_PORT') ? C('DATA_REDIS_PORT') : 6379, 'timeout' => C('DATA_CACHE_TIME') ? C('DATA_CACHE_TIME') : false, 'persistent' => C('DATA_PERSISTENT') ? C('DATA_PERSISTENT') : false,'auth'=> C('DATA_REDIS_AUTH') ? C('DATA_REDIS_AUTH') : false, ); }$options['host'] = explode(',', $options['host']);$options['port'] = explode(',', $options['port']);$options['auth'] = explode(',', $options['auth']);foreach ($options['host'] as $key=>$value) {if (!isset($options['port'][$key])) {$options['port'][$key] = $options['port'][0];}if (!isset($options['auth'][$key])) {$options['auth'][$key] = $options['auth'][0];}} self::$option = $options; self::$option['expire'] = isset($options['expire']) ? $options['expire'] : C('DATA_EXPIRE'); self::$option['prefix'] = isset($options['prefix']) ? $options['prefix'] : C('DATA_CACHE_PREFIX'); self::$option['length'] = isset($options['length']) ? $options['length'] : 0; // 一次性创建redis的在不同host的实例 foreach(self::$option['host'] as $i=>$server) { $host=self::$option['host'][$i]; $port=self::$option['port'][$i]; $auth=self::$option['auth'][$i];if(!(self::$_instance[$i] instanceof self)) {self::$_instance[$i]=new self($host,intval($port),$auth);}}// 默认返回第一个实例,即masterreturn self::$_instance[0];}/***判断是否master/slave,调用不同的master或者slave实例**/public function is_master($master=true) {if($master) {$i=0;}else {$count=count(self::$option['host']);if($count==1) {$i=0;}else{$i=rand(1,$count - 1);}}//返回每一个实例的句柄return self::$_instance[$i]->handler;}/** * 读取缓存,随机从slave服务器中读缓存 * @access public * @param string $name 缓存变量名 * @return mixed */ public function get($name) {$redis=$this->is_master(false); N('cache_read',1); $value = $redis->get(self::$option['prefix'].$name); $jsonData = json_decode( $value, true ); //检测是否为JSON数据 true 返回JSON解析数组, false返回源数据 return ($jsonData === NULL) ? $value : $jsonData; } /** * 写入缓存,写入master的redis服务器 * @access public * @param string $name 缓存变量名 * @param mixed $value 存储数据 * @param integer $expire 有效时间(秒) * @return boolean */ public function set($name, $value, $expire = null) {$redis=$this->is_master(true); N('cache_write',1); if(is_null($expire)) { $expire = self::$option['expire']; } $name = self::$option['prefix'].$name; //对数组/对象数据进行缓存处理,保证数据完整性 $value = (is_object($value) || is_array($value)) ? json_encode($value) : $value; if(is_int($expire) && $expire > 0) { $result = $redis->setex($name, $expire, $value); }else{ $result = $redis->set($name, $value); } if($result && self::$option['length']>0) { // 记录缓存队列 $this->queue($name); } return $result; } /** * 删除缓存 * @access public * @param string $name 缓存变量名 * @return boolean */ public function rm($name) {$redis=$this->is_master(true); return $redis->delete(self::$option['prefix'].$name); } /** * 清除缓存 * @access public * @return boolean */ public function clear() {$redis=$this->is_master(true); return $redis->flushDB(); } /** *禁止外部克隆对象 * */ private function __clone() { } //可以根据需要,继续添加phpredis的驱动api. /** * 关闭长连接 * @access public */public function __destruct() {if (self::$option['persistent'] == 'pconnect') {// 关闭master的长连接,不可以写,但slave任然可以读$redis=$this->is_master(true);$redis->close();}}}
3、CONTROLLER中用法
$redis=\Think\Cache\Driver\Redisrw::getInstance();$redis->set('address','beijing');$result=$redis->get('address');dump($result);
0 1
- thinkphp的redis主从分布式的单例模式
- Redis的主从模式
- redis的主从模式
- redis单例、主从模式、sentinel以及集群的配置方式及优缺点对比
- 基于单Redis节点的分布式锁
- thinkphp 3.2里面session的redis驱动文件(可分布式)
- Redis的主从模式-Redis学习笔记五
- Redis的主从架构(主从&主从从)
- Redis的主从复制
- Redis的主从机制
- Redis的主从复制
- redis的主从配置
- redis的主从复制
- Redis的主从复制
- Redis的主从复制
- Redis的主从复制
- Redis的主从复制
- Redis的主从同步
- hdu1709 The Balance (放入+取出 01背包)
- iOS地理定位
- 一个好的界面设计应该注意的75个原则
- java中读取文件的方法
- 138,Swift的认识
- thinkphp的redis主从分布式的单例模式
- (NO.00005)iOS实现炸弹人游戏(六):游戏数据的初始化(三)
- 颜色
- 安卓学习记录-java-day6
- Spark:大数据的“电光石火”
- 对Linux CAN驱动的理解
- javac编译
- bitset用法及应用
- 学习使用apache comments io包中的IOUtils中的方法