Yii 框架中使用redis缓存数据

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Yii框架中可以自由配置缓存方式,比如最常用的memcache/memcahed,只需要在config中添加如下配置信息即可。

Source code	          
'cache' => array (
    'class' => 'system.caching.CMemCache',
    'servers' => array (
          array (
            'host' => '127.0.0.1',
            'port' => 11211,
            'weight' => 60 
          ) 
        ),
        'hashKey' => false,
        'serializer' => false,
        'useMemcached' => true 
    )
使用方法也很方便。

Source code	          

  Yii::app()->cache->set('aaaa','value');
Radis 作为一个内存型数据库,我们通常会将它作为可长时间将数据存贮到内存中的缓存系统,事实上不能及时做持久化处理的存储系统都是不稳定的。对于传统的key-value缓存系统而言,radis又同时支持多种数据结构(String,List,Set,Map,StoredSet),有关支持的数据类型可以参考redis中文站点 猛击我 。

支持多种数据结构意味着我们能够利用这些数据结构特性,展开一些特定的业务,比如在之前的项目当中使用的时间轴。如果用传统数据库实现性能会相当低下,既要考虑多种表交叉重组,又要考虑重组后的分页问题。如果用非关系型数据库就会很方便的处理,利用List特性就可以方便的“压入”用户的历史数据。

先来看一下如何配置一个redis缓存。

Source code	          
'redis_cache' => array (
  'class' => 'system.caching.CRedisCache',
  'hostname' =>'127.0.0.1',
  'port'=>6379,
  'password'=>'123456',
  'database'=>0
) 
//使用方法
Yii::app()->redis_cache->set('aaaa','value');
利用Yii框架中的caching.CRedisCache类,password是部署服务器当中的auth配置。

使用方法和使用memcache/memcahced中的cache一样,直接set/get即可。

看一下CRedisCached这个实现类

Source code	          


 * @link http://www.yiiframework.com/

 * @copyright 2008-2013 Yii Software LLC

 * @license http://www.yiiframework.com/license/

 */
/**
 * CRedisCache implements a cache application component based on {@link http://redis.io/ redis}.

 *
 * CRedisCache needs to be configured with {@link hostname}, {@link port} and {@link database} of the server

 * to connect to. By default CRedisCache assumes there is a redis server running on localhost at

 * port 6379 and uses the database number 0.

 *
 * CRedisCache also supports {@link http://redis.io/commands/auth the AUTH command} of redis.

 * When the server needs authentication, you can set the {@link password} property to

 * authenticate with the server after connect.

 *
 * See {@link CCache} manual for common cache operations that are supported by CRedisCache.

 *
 * To use CRedisCache as the cache application component, configure the application as follows,

 * 
 * array(
 * 'components'=>array(

 * 'cache'=>array(

 * 'class'=>'CRedisCache',

 * 'hostname'=>'localhost',

 * 'port'=>6379,

 * 'database'=>0,

 * ),
 * ),
 * )
 * 
 *  * The minimum required redis version is 2.0.0.  *  * @author Carsten Brandt   * @package system.caching  * @since 1.1.14  */ class CRedisCache extends CCache { /** * @var string hostname to use for connecting to the redis server. Defaults to 'localhost'. */ public $hostname = 'localhost' ; /** * @var int the port to use for connecting to the redis server. Default port is 6379. */ public $port = 6379 ; /** * @var string the password to use to authenticate with the redis server. If not set, no AUTH command will be sent. */ public $password ; /** * @var int the redis database to use. This is an integer value starting from 0. Defaults to 0. */ public $database = 0 ; /** * @var float timeout to use for connection to redis. If not set the timeout set in php.ini will be used: ini_get("default_socket_timeout") */ public $timeout = null ; /** * @var resource redis socket connection */ private $_socket ; /** * Establishes a connection to the redis server. * It does nothing if the connection has already been established. * @throws CException if connecting fails */ protected function connect ( ) { $this -> _socket =@ stream_socket_client ( $this -> hostname . ':' . $this -> port , $errorNumber , $errorDescription , $this -> timeout ? $this -> timeout : ini_get ( "default_socket_timeout" ) ) ; if ( $this -> _socket ) { if ( $this -> password !== null ) $this -> executeCommand ( 'AUTH' , array ( $this -> password ) ) ; $this -> executeCommand ( 'SELECT' , array ( $this -> database ) ) ; } else throw new CException ( 'Failed to connect to redis: ' . $errorDescription , ( int ) $errorNumber ) ; } /** * Executes a redis command. * For a list of available commands and their parameters see {@link http://redis.io/commands}. * * @param string $name the name of the command * @param array $params list of parameters for the command * @return array|bool|null|string Dependend on the executed command this method * will return different data types: * 
  • true for commands that return "status reply".
  • string for commands that return "integer reply" * as the value is in the range of a signed 64 bit integer.
  • string or null for commands that return "bulk reply".
  • array for commands that return "Multi-bulk replies".
* See {@link http://redis.io/topics/protocol redis protocol description} * for details on the mentioned reply types. * @trows CException for commands that return {@link http://redis.io/topics/protocol#error-reply error reply}. */ public function executeCommand ( $name , $params = array ( ) ) { if ( $this -> _socket === null ) $this -> connect ( ) ; array_unshift ( $params , $name ) ; $command = '*' . count ( $params ) . " \r \n " ; foreach ( $params as $arg ) $command .= '$' . strlen ( $arg ) . " \r \n " . $arg . " \r \n " ; fwrite ( $this -> _socket , $command ) ; return $this -> parseResponse ( implode ( ' ' , $params ) ) ; } /** * Reads the result from socket and parses it * @return array|bool|null|string * @throws CException socket or data problems */ private function parseResponse ( ) { if ( ( $line = fgets ( $this -> _socket ) ) === false ) throw new CException ( 'Failed reading data from redis connection socket.' ) ; $type = $line [ 0 ] ; $line = substr ( $line , 1 ,- 2 ) ; switch ( $type ) { case '+' : // Status reply return true ; case '-' : // Error reply throw new CException ( 'Redis error: ' . $line ) ; case ':' : // Integer reply // no cast to int as it is in the range of a signed 64 bit integer return $line ; case '$' : // Bulk replies if ( $line == '-1' ) return null ; $length = $line + 2 ; $data = '' ; while ( $length > 0 ) { if ( ( $block = fread ( $this -> _socket , $length ) ) === false ) throw new CException ( 'Failed reading data from redis connection socket.' ) ; $data .= $block ; $length -= ( function_exists ( 'mb_strlen' ) ? mb_strlen ( $block , '8bit' ) : strlen ( $block ) ) ; } return substr ( $data , 0 ,- 2 ) ; case '*' : // Multi-bulk replies $count = ( int ) $line ; $data = array ( ) ; for ( $i = 0 ; $i < $count ; $i ++ ) $data [ ] = $this -> parseResponse ( ) ; return $data ; default : throw new CException ( 'Unable to parse data received from redis.' ) ; } } /** * Retrieves a value from cache with a specified key. * This is the implementation of the method declared in the parent class. * @param string $key a unique key identifying the cached value * @return string|boolean the value stored in cache, false if the value is not in the cache or expired. */ protected function getValue ( $key ) { return $this -> executeCommand ( 'GET' , array ( $key ) ) ; } /** * Retrieves multiple values from cache with the specified keys. * @param array $keys a list of keys identifying the cached values * @return array a list of cached values indexed by the keys */ protected function getValues ( $keys ) { $response = $this -> executeCommand ( 'MGET' , $keys ) ; $result = array ( ) ; $i = 0 ; foreach ( $keys as $key ) $result [ $key ] = $response [ $i ++ ] ; return $result ; } /** * Stores a value identified by a key in cache. * This is the implementation of the method declared in the parent class. * * @param string $key the key identifying the value to be cached * @param string $value the value to be cached * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. * @return boolean true if the value is successfully stored into cache, false otherwise */ protected function setValue ( $key , $value , $expire ) { if ( $expire == 0 ) return ( bool ) $this -> executeCommand ( 'SET' , array ( $key , $value ) ) ; return ( bool ) $this -> executeCommand ( 'SETEX' , array ( $key , $expire , $value ) ) ; } /** * Stores a value identified by a key into cache if the cache does not contain this key. * This is the implementation of the method declared in the parent class. * * @param string $key the key identifying the value to be cached * @param string $value the value to be cached * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire. * @return boolean true if the value is successfully stored into cache, false otherwise */ protected function addValue ( $key , $value , $expire ) { if ( $expire == 0 ) return ( bool ) $this -> executeCommand ( 'SETNX' , array ( $key , $value ) ) ; if ( $this -> executeCommand ( 'SETNX' , array ( $key , $value ) ) ) { $this -> executeCommand ( 'EXPIRE' , array ( $key , $expire ) ) ; return true ; } else return false ; } /** * Deletes a value with the specified key from cache * This is the implementation of the method declared in the parent class. * @param string $key the key of the value to be deleted * @return boolean if no error happens during deletion */ protected function deleteValue ( $key ) { return ( bool ) $this -> executeCommand ( 'DEL' , array ( $key ) ) ; } /** * Deletes all values from cache. * This is the implementation of the method declared in the parent class. * @return boolean whether the flush operation was successful. */ protected function flushValues ( ) { return $this -> executeCommand ( 'FLUSHDB' ) ; } } 可以看出Yii并没有使用其他的redis扩展,现在流行的PHP redis连接方式主要有两种。其他参见 其他client predis:一个不需要安装PHP扩展的连接Redis的组件包 PHP-redis:一个redis的php扩展 看源码可以看到,Yii使用的是stream_socket_client这种方式连接的redis服务器。我们模拟一下看看 Source code            $socket=@stream_socket_client(     '127.0.0.1:6379',     $errorNumber,     $errorDescription,     300 ); var_dump($socket); 使用这种方法可以顺利的连接到远程socket端口,其实以前如果用过的话就能知道,其实MySql也是可以用这种方式获得连接的。但不提倡,暂时先用这种方法,有时间再来利用扩展。 已经很强大了,可这满足不了我们目前的需要。该类集成自CCache只实现了其中的set get方法,其他的并没有实现,而更多地是需要我们借助executeCommand($name,$params=array())这个方法来完成我们想要的操作。所以我们需要对该方法做进一步封装,利用executeCommand。 我们首先扩展一个List左侧压入一个数据的操作 Source code            /**  * @author Abel  * email:[email protected]  * 2014-1-17  * UTF-8  */ class ZRedisCache extends CRedisCache{       /**      * 左侧压入一个数据      * @param String $key      * @param String $value      * @return int      */     public function lpush($key,$value){         if(!is_string($value)){             throw new Exception('The value type is not a string.If u want to push an array data.You can use JSON.');         }         $num = $this->executeCommand('LPUSH',array($key,$value));         return intval($num);     } } 3F2258B8-1DE1-4794-812A-47AFA9507D76 可以看到数据都可以顺利的压入列队当中。


转载于:https://my.oschina.net/yonghan/blog/534594

你可能感兴趣的:(Yii 框架中使用redis缓存数据)