PHP 操作redis 封装的类

  1 <?php
  2 /**
  3  * Redis 操作,支持 Master/Slave 的负载集群
  4  *  6  */
  7 class RedisCluster{
  8        
  9     // 是否使用 M/S 的读写集群方案    
 10     private $_isUseCluster = false;
 11        
 12     // Slave 句柄标记    
 13     private $_sn = 0;
 14        
 15     // 服务器连接句柄    
 16     private $_linkHandle = array(
 17         'master'=>null,// 只支持一台 Master       
 18         'slave'=>array(),// 可以有多台 Slave    
 19     );
 20        
 21     /**
 22      * 构造函数
 23      *
 24      * @param boolean $isUseCluster 是否采用 M/S 方案
 25      */    
 26     public function __construct($isUseCluster=false){
 27         $this->_isUseCluster = $isUseCluster;
 28     }
 29        
 30     /**
 31      * 连接服务器,注意:这里使用长连接,提高效率,但不会自动关闭
 32      *
 33      * @param array $config Redis服务器配置
 34      * @param boolean $isMaster 当前添加的服务器是否为 Master 服务器
 35      * @return boolean
 36      */    
 37     public function connect($config=array('host'=>'127.0.0.1','port'=>6379), $isMaster=true){
 38         // default port        
 39         if(!isset($config['port'])){
 40             $config['port'] = 6379;
 41         }
 42         // 设置 Master 连接        
 43        if($isMaster){
 44             $this->_linkHandle['master'] = new Redis();
 45             $ret = $this->_linkHandle['master']->pconnect($config['host'],$config['port']);
 46         }else{
 47             // 多个 Slave 连接            
 48         $this->_linkHandle['slave'][$this->_sn] = new Redis();
 49             $ret = $this->_linkHandle['slave'][$this->_sn]->pconnect($config['host'],$config['port']);
 50             ++$this->_sn;
 51         }
 52         return $ret;
 53     }
 54        
 55     /**
 56      * 关闭连接
 57      *
 58      * @param int $flag 关闭选择 0:关闭 Master 1:关闭 Slave 2:关闭所有
 59      * @return boolean
 60      */    
 61     public function close($flag=2){
 62         switch($flag){
 63             // 关闭 Master            
 64             case 0:                
 65                 $this->getRedis()->close();
 66             break;
 67             // 关闭 Slave            
 68             case 1:                
 69                 for($i=0; $i<$this->_sn; ++$i){
 70                     $this->_linkHandle['slave'][$i]->close();
 71                 }
 72             break;
 73             // 关闭所有            
 74             case 2:                
 75                 $this->getRedis()->close();
 76                 for($i=0; $i<$this->_sn; ++$i){
 77                     $this->_linkHandle['slave'][$i]->close();
 78                 }
 79             break;
 80         }
 81         return true;
 82     }
 83        
 84     /**
 85      * 得到 Redis 原始对象可以有更多的操作
 86      *
 87      * @param boolean $isMaster 返回服务器的类型 true:返回Master false:返回Slave
 88      * @param boolean $slaveOne 返回的Slave选择 true:负载均衡随机返回一个Slave选择 false:返回所有的Slave选择
 89      * @return redis object
 90      */    
 91     public function getRedis($isMaster=true,$slaveOne=true){
 92         // 只返回 Master        
 93         if($isMaster){
 94             return $this->_linkHandle['master'];
 95         }else{
 96             return $slaveOne ? $this->_getSlaveRedis() : $this->_linkHandle['slave'];
 97         }
 98     }
 99        
100     /**
101      * 写缓存
102      *
103      * @param string $key 组存KEY
104      * @param string $value 缓存值
105      * @param int $expire 过期时间, 0:表示无过期时间
106      */    
107     public function set($key, $value, $expire=0){
108         // 永不超时        
109         if($expire == 0){
110             $ret = $this->getRedis()->set($key, $value);
111         }else{
112             $ret = $this->getRedis()->setex($key, $expire, $value);
113         }
114         return $ret;
115     }
116        
117     /**
118      * 读缓存
119      *
120      * @param string $key 缓存KEY,支持一次取多个 $key = array('key1','key2')
121      * @return string || boolean  失败返回 false, 成功返回字符串
122      */    
123     public function get($key){
124         // 是否一次取多个值        
125         $func = is_array($key) ? 'mGet' : 'get';
126         // 没有使用M/S        
127         if(! $this->_isUseCluster){
128             return $this->getRedis()->{$func}($key);
129         }
130         // 使用了 M/S        
131         return $this->_getSlaveRedis()->{$func}($key);
132     }
133        
134     /**
135      * 条件形式设置缓存,如果 key 不存时就设置,存在时设置失败
136      *
137      * @param string $key 缓存KEY
138      * @param string $value 缓存值
139      * @return boolean
140      */    
141     public function setnx($key, $value){
142         return $this->getRedis()->setnx($key, $value);
143     }
144        
145     /**
146      * 删除缓存
147      *
148      * @param string || array $key 缓存KEY,支持单个健:"key1" 或多个健:array('key1','key2')
149      * @return int 删除的健的数量
150      */   
151      public function remove($key){
152         // $key => "key1" || array('key1','key2')       
153          return $this->getRedis()->delete($key);
154     }
155        
156     /**
157      * 值加加操作,类似 ++$i ,如果 key 不存在时自动设置为 0 后进行加加操作
158      *
159      * @param string $key 缓存KEY
160      * @param int $default 操作时的默认值
161      * @return int 操作后的值
162      */    
163     public function incr($key,$default=1){
164         if($default == 1){
165             return $this->getRedis()->incr($key);
166         }else{
167             return $this->getRedis()->incrBy($key, $default);
168         }
169     }
170        
171     /**
172      * 值减减操作,类似 --$i ,如果 key 不存在时自动设置为 0 后进行减减操作
173      *
174      * @param string $key 缓存KEY
175      * @param int $default 操作时的默认值
176      * @return int 操作后的值
177      */    
178     public function decr($key,$default=1){
179         if($default == 1){
180             return $this->getRedis()->decr($key);
181         }else{
182             return $this->getRedis()->decrBy($key, $default);
183         }
184     }
185        
186     /**
187      * 添空当前数据库
188      *
189      * @return boolean
190      */    
191     public function clear(){
192         return $this->getRedis()->flushDB();
193     }
194        
195     /* =================== 以下私有方法 =================== */       
196     /**
197      * 随机 HASH 得到 Redis Slave 服务器句柄
198      *
199      * @return redis object
200      */    
201     private function _getSlaveRedis(){
202         // 就一台 Slave 机直接返回        
203         if($this->_sn <= 1){
204             return $this->_linkHandle['slave'][0];
205         }
206         // 随机 Hash 得到 Slave 的句柄        
207         $hash = $this->_hashId(mt_rand(), $this->_sn);
208         return $this->_linkHandle['slave'][$hash];
209     }
210        
211     /**
212      * 根据ID得到 hash 后 0~m-1 之间的值
213      *
214      * @param string $id
215      * @param int $m
216      * @return int
217      */    
218     private function _hashId($id,$m=10)
219     {
220         //把字符串K转换为 0~m-1 之间的一个值作为对应记录的散列地址                
221         $k = md5($id);
222         $l = strlen($k);
223         $b = bin2hex($k);
224         $h = 0;
225         for($i=0;$i<$l;$i++)
226         {
227             //相加模式HASH            
228             $h += substr($b,$i*2,2);
229         }
230         $hash = ($h*1)%$m;
231         return $hash;
232     }
233        
234 }// End Class
235        
236 // ================= TEST DEMO =================
237        
238 // 只有一台 Redis 的应用$redis = new RedisCluster();$redis->connect(array('host'=>'127.0.0.1','port'=>6379));$redis->set('id',35);var_dump($redis->get('id'));
239        
240        // 有一台 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){
241     var_dump($redis->get('id')).PHP_EOL;
242 }
243        // phpRedis 扩展的更多高级操作$redis = new RedisCluster();$redis->connect(array('host'=>'127.0.0.1','port'=>6379));$ret = $redis->getRedis()->ping();// phpRedis 原始APIvar_dump($ret);                                    

 

posted @ 2016-08-04 11:40  CandyChen  阅读(2024)  评论(1编辑  收藏  举报