redis是什么。redis 是一个高性能的key-value数据库。

redis的三个主要特点:
1,redis将其数据库完全保存在内存中,仅使用磁盘进行持久化。
2,与其它键值数据存储相比,redis有一组相对丰富的数据类型。
3,redis可以将数据复制到任意数量的从机中。

redis的一些优点:
1,异常快 – redis非常快,每秒可执行大约110000次的设置(SET)操作,每秒大约可执行81000次的读取/获取(GET)操作。
2,支持丰富的数据类型 – redis支持开发人员常用的大多数数据类型,例如列表,集合,排序集和散列等等。这使得redis很容易被用来解决各种问题,因为我们知道哪些问题可以更好使用地哪些数据类型来处理解决。
3,操作具有原子性 – 所有redis操作都是原子操作,这确保如果两个客户端并发访问,Redis服务器能接收更新的值。
4,多实用工具 – redis是一个多实用工具,可用于多种用例,如:缓存,消息队列(Redis本地支持发布/订阅),应用程序中的任何短期数据,例如,web应用程序中的会话,网页命中计数等。

redis百度百科

redis官网

redis中文官方网站

redis易百教程

既然redis有它的优点,那么学习和使用它也是必然的。自己只会点简单的ci框架,得想办法将ci框架和redis结合在一起使用。ci3已经支持redis。他们说ci支持的redis还不够强大。于是出现了一些扩展和实现。基本步骤如下。
1,服务端必须先安装和开启redis,并安装php对应的redis扩展。
2,ci中配置redis。无论是自定义还是使用ci的redis都要先配置redis。在“application/config/”目录下,创建redis.php。

<?php
defined('BASEPATH') OR exit('No direct script access allowed'); 
$config = array(
    'socket_type' => 'tcp',
    'host' => '127.0.0.1',
    'port' => 6379,
    'password' => NULL,
    'timeout' => 0
    );

2,“application/config/autoload.php”中开启自动加载。
3,通常,ci框架中,system下的文件我们是不会去修改的。操作和扩展都是在application下进行。在“application/libraries/”下,创建CI_Redis.php库。

<?php defined('BASEPATH') OR exit('No direct script access allowed');  
/** 
 * CodeIgniter Redis 
 * 
 * A CodeIgniter library to interact with Redis 
 * 
 * @package         CodeIgniter 
 * @category        Libraries 
 * @author          Joël Cox 
 * @version         v0.4 
 * @link            https://github.com/joelcox/codeigniter-redis 
 * @link            http://joelcox.nl 
 * @license         http://www.opensource.org/licenses/mit-license.html 
 */  
class CI_Redis {  
  
    /** 
     * CI 
     * 
     * CodeIgniter instance 
     * @var     object 
     */  
    private $_ci;  
  
    /** 
     * Connection 
     * 
     * Socket handle to the Redis server 
     * @var     handle 
     */  
    private $_connection;  
  
    /** 
     * Debug 
     * 
     * Whether we're in debug mode 
     * @var     bool 
     */  
    public $debug = FALSE;  
  
    /** 
     * CRLF 
     * 
     * User to delimiter arguments in the Redis unified request protocol 
     * @var     string 
     */  
    const CRLF = "\r\n";  
  
    /** 
     * Constructor 
     */  
    public function __construct($params = array())  
    {  
  
        log_message('debug', 'Redis Class Initialized');  
  
        $this->_ci = get_instance();  
        $this->_ci->load->config('redis');  
  
        // Check for the different styles of configs  
        if (isset($params['connection_group']))  
        {  
            // Specific connection group  
            $config = $this->_ci->config->item('redis_' . $params['connection_group']);  
        }  
        elseif (is_array($this->_ci->config->item('redis_default')))  
        {  
            // Default connection group  
            $config = $this->_ci->config->item('redis_default');  
        }  
        else  
        {  
            // Original config style  
            $config = array(  
                'host' => $this->_ci->config->item('redis_host'),  
                'port' => $this->_ci->config->item('redis_port'),  
                'password' => $this->_ci->config->item('redis_password'),  
            );  
        }  
  
        // Connect to Redis  
        $this->_connection = @fsockopen($config['host'], $config['port'], $errno, $errstr, 3);  
  
        // Display an error message if connection failed  
        if ( ! $this->_connection)  
        {  
            show_error('Could not connect to Redis at ' . $config['host'] . ':' . $config['port']);  
        }  
  
        // Authenticate when needed  
        $this->_auth($config['password']);  
  
    }  
  
    /** 
     * Call 
     * 
     * Catches all undefined methods 
     * @param   string  method that was called 
     * @param   mixed   arguments that were passed 
     * @return  mixed 
     */  
    public function __call($method, $arguments)  
    {  
        $request = $this->_encode_request($method, $arguments);  
        return $this->_write_request($request);  
    }  
  
    /** 
     * Command 
     * 
     * Generic command function, just like redis-cli 
     * @param   string  full command as a string 
     * @return  mixed 
     */  
    public function command($string)  
    {  
        $slices = explode(' ', $string);  
        $request = $this->_encode_request($slices[0], array_slice($slices, 1));  
  
        return $this->_write_request($request);  
    }  
  
    /** 
     * Auth 
     * 
     * Runs the AUTH command when password is set 
     * @param   string  password for the Redis server 
     * @return  void 
     */  
    private function _auth($password = NULL)  
    {  
  
        // Authenticate when password is set  
        if ( ! empty($password))  
        {  
  
            // See if we authenticated successfully  
            if ($this->command('AUTH ' . $password) !== 'OK')  
            {  
                show_error('Could not connect to Redis, invalid password');  
            }  
  
        }  
  
    }  
  
    /** 
     * Clear Socket 
     * 
     * Empty the socket buffer of theconnection so data does not bleed over 
     * to the next message. 
     * @return  NULL 
     */  
    public function _clear_socket()  
    {  
        // Read one character at a time  
        fflush($this->_connection);  
        return NULL;  
    }  
  
    /** 
     * Write request 
     * 
     * Write the formatted request to the socket 
     * @param   string  request to be written 
     * @return  mixed 
     */  
    private function _write_request($request)  
    {  
        if ($this->debug === TRUE)  
        {  
            log_message('debug', 'Redis unified request: ' . $request);  
        }  
  
        // How long is the data we are sending?  
        $value_length = strlen($request);  
  
        // If there isn't any data, just return  
        if ($value_length <= 0) return NULL;  
  
  
        // Handle reply if data is less than or equal to 8192 bytes, just send it over  
        if ($value_length <= 8192)  
        {  
            fwrite($this->_connection, $request);  
        }  
        else  
        {  
            while ($value_length > 0)  
            {  
  
                // If we have more than 8192, only take what we can handle  
                if ($value_length > 8192) {  
                    $send_size = 8192;  
                }  
  
                // Send our chunk  
                fwrite($this->_connection, $request, $send_size);  
  
                // How much is left to send?  
                $value_length = $value_length - $send_size;  
  
                // Remove data sent from outgoing data  
                $request = substr($request, $send_size, $value_length);  
  
            }  
        }  
  
        // Read our request into a variable  
        $return = $this->_read_request();  
  
        // Clear the socket so no data remains in the buffer  
        $this->_clear_socket();  
  
        return $return;  
    }  
  
    /** 
     * Read request 
     * 
     * Route each response to the appropriate interpreter 
     * @return  mixed 
     */  
    private function _read_request()  
    {  
        $type = fgetc($this->_connection);  
  
        // Times we will attempt to trash bad data in search of a  
        // valid type indicator  
        $response_types = array('+', '-', ':', '$', '*');  
        $type_error_limit = 50;  
        $try = 0;  
  
        while ( ! in_array($type, $response_types) && $try < $type_error_limit)  
        {  
            $type = fgetc($this->_connection);  
            $try++;  
        }  
  
        if ($this->debug === TRUE)  
        {  
            log_message('debug', 'Redis response type: ' . $type);  
        }  
  
        switch ($type)  
        {  
            case '+':  
                return $this->_single_line_reply();  
                break;  
            case '-':  
                return $this->_error_reply();  
                break;  
            case ':':  
                return $this->_integer_reply();  
                break;  
            case '$':  
                return $this->_bulk_reply();  
                break;  
            case '*':  
                return $this->_multi_bulk_reply();  
                break;  
            default:  
                return FALSE;  
        }  
  
    }  
  
    /** 
     * Single line reply 
     * 
     * Reads the reply before the EOF 
     * @return  mixed 
     */  
    private function _single_line_reply()  
    {  
        $value = rtrim(fgets($this->_connection));  
        $this->_clear_socket();  
  
        return $value;  
    }  
  
    /** 
     * Error reply 
     * 
     * Write error to log and return false 
     * @return  bool 
     */  
    private function _error_reply()  
    {  
        // Extract the error message  
        $error = substr(rtrim(fgets($this->_connection)), 4);  
  
        log_message('error', 'Redis server returned an error: ' . $error);  
        $this->_clear_socket();  
  
        return FALSE;  
    }  
  
    /** 
     * Integer reply 
     * 
     * Returns an integer reply 
     * @return  int 
     */  
    private function _integer_reply()  
    {  
        return (int) rtrim(fgets($this->_connection));  
    }  
  
    /** 
     * Bulk reply 
     * 
     * Reads to amount of bits to be read and returns value within 
     * the pointer and the ending delimiter 
     * @return  string 
     */  
    private function _bulk_reply()  
    {  
  
        // How long is the data we are reading? Support waiting for data to  
        // fully return from redis and enter into socket.  
        $value_length = (int) fgets($this->_connection);  
  
        if ($value_length <= 0) return NULL;  
  
        $response = '';  
  
        // Handle reply if data is less than or equal to 8192 bytes, just read it  
        if ($value_length <= 8192)  
        {  
            $response = fread($this->_connection, $value_length);  
        }  
        else  
        {  
            $data_left = $value_length;  
  
                // If the data left is greater than 0, keep reading  
                while ($data_left > 0 ) {  
  
                // If we have more than 8192, only take what we can handle  
                if ($data_left > 8192)  
                {  
                    $read_size = 8192;  
                }  
                else  
                {  
                    $read_size = $data_left;  
                }  
  
                // Read our chunk  
                $chunk = fread($this->_connection, $read_size);  
  
                // Support reading very long responses that don't come through  
                // in one fread  
  
                $chunk_length = strlen($chunk);  
                while ($chunk_length < $read_size)  
                {  
                    $keep_reading = $read_size - $chunk_length;  
                    $chunk .= fread($this->_connection, $keep_reading);  
                    $chunk_length = strlen($chunk);  
                }  
  
                $response .= $chunk;  
  
                // Re-calculate how much data is left to read  
                $data_left = $data_left - $read_size;  
  
            }  
  
        }  
  
        // Clear the socket in case anything remains in there  
        $this->_clear_socket();  
  
    return isset($response) ? $response : FALSE;  
    }  
  
    /** 
     * Multi bulk reply 
     * 
     * Reads n bulk replies and return them as an array 
     * @return  array 
     */  
    private function _multi_bulk_reply()  
    {  
        // Get the amount of values in the response  
        $response = array();  
        $total_values = (int) fgets($this->_connection);  
  
        // Loop all values and add them to the response array  
        for ($i = 0; $i < $total_values; $i++)  
        {  
            // Remove the new line and carriage return before reading  
            // another bulk reply  
            fgets($this->_connection, 2);  
  
            // If this is a second or later pass, we also need to get rid  
            // of the $ indicating a new bulk reply and its length.  
            if ($i > 0)  
            {  
                fgets($this->_connection);  
                fgets($this->_connection, 2);  
            }  
  
            $response[] = $this->_bulk_reply();  
  
        }  
  
        // Clear the socket  
        $this->_clear_socket();  
  
        return isset($response) ? $response : FALSE;  
    }  
  
    /** 
     * Encode request 
     * 
     * Encode plain-text request to Redis protocol format 
     * @link    http://redis.io/topics/protocol 
     * @param   string  request in plain-text 
     * @param   string  additional data (string or array, depending on the request) 
     * @return  string  encoded according to Redis protocol 
     */  
    private function _encode_request($method, $arguments = array())  
    {  
        $request = '$' . strlen($method) . self::CRLF . $method . self::CRLF;  
        $_args = 1;  
  
        // Append all the arguments in the request string  
        foreach ($arguments as $argument)  
        {  
            if (is_array($argument))  
            {  
                foreach ($argument as $key => $value)  
                {  
                    // Prepend the key if we're dealing with a hash  
                    if (!is_int($key))  
                    {  
                        $request .= '$' . strlen($key) . self::CRLF . $key . self::CRLF;  
                        $_args++;  
                    }  
  
                    $request .= '$' . strlen($value) . self::CRLF . $value . self::CRLF;  
                    $_args++;  
                }  
            }  
            else  
            {  
                $request .= '$' . strlen($argument) . self::CRLF . $argument . self::CRLF;  
                $_args++;  
            }  
        }  
  
        $request = '*' . $_args . self::CRLF . $request;  
  
        return $request;  
    }  
  
    /** 
     * Info 
     * 
     * Overrides the default Redis response, so we can return a nice array 
     * of the server info instead of a nasty string. 
     * @return  array 
     */  
    public function info($section = FALSE)  
    {  
        if ($section !== FALSE)  
        {  
            $response = $this->command('INFO '. $section);  
        }  
        else  
        {  
            $response = $this->command('INFO');  
        }  
  
        $data = array();  
        $lines = explode(self::CRLF, $response);  
  
        // Extract the key and value  
        foreach ($lines as $line)  
        {  
            $parts = explode(':', $line);  
            if (isset($parts[1])) $data[$parts[0]] = $parts[1];  
        }  
  
        return $data;  
    }  
  
    /** 
     * Debug 
     * 
     * Set debug mode 
     * @param   bool    set the debug mode on or off 
     * @return  void 
     */  
    public function debug($bool)  
    {  
        $this->debug = (bool) $bool;  
    }  
  
    /** 
     * Destructor 
     * 
     * Kill the connection 
     * @return  void 
     */  
    function __destruct()  
    {  
        if ($this->_connection) fclose($this->_connection);  
    }  
}  

然后,就可以使用了。

<?php  
    if($this->redis->get('mark_'.$gid) === null)
    {     //如果未设置   
        $this->redis->set('mark_'.$gid, $giftnum); //设置  
        $this->redis->EXPIRE('mark_'.$gid, 30*60); //设置过期时间 (30 min)  
    }
    else
    {  
        //从缓存中直接读取对应的值  
        $giftnum =  $this->redis->get('mark_'.$gid);  
    } 

使用位置:
为了保证model的干净,通常在controller中使用redis。如果是复用性以及少操作性,觉得放在model里边不是更好么。打个比方,一个model可能被多个controller使用。而这多个controller都会去model中请求某一份相同数据。这种场景下,在model中使用不是更好么。

CI框架中使用redis的相关博客:
http://www.mamicode.com/info-detail-1551321.html

http://blog.csdn.net/wzj0808/article/details/54948971

http://blog.csdn.net/wujiangwei567/article/details/50607364

http://www.cnblogs.com/mvpchenjian/p/6251706.html