Thinkphp 3.2.3 redis缓存

说明

好像是tp3.2的bug,自带的redis驱动不是那么好用。。。找了方法修改优化了一下,亲测可用。

  1. 确认已经安装了redis服务器
  2. 确认php中已经安装了redis扩展
  3. TP版本:thinkphp_3.2.3_full.zip

S缓存使用redis

复制以下内容到文本中,改名为Redis.class.php。
替换ThinkPHP\Library\Think\Cache\Driver\Redis.class.php(注意先备份)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<?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 )
// +----------------------------------------------------------------------
namespace Think\Cache\Driver;
use Think\Cache;
defined('THINK_PATH') or exit();

/**
* Redis缓存驱动
*/
class Redis extends Cache {
/**
* 架构函数
* @param array $options 缓存参数
* @access public
*/
public function __construct($options=array()) {
if ( !extension_loaded('redis') ) {
E(L('_NOT_SUPPERT_').':redis');
}
if(empty($options)) {
$options = array (
'host' => C('REDIS_HOST') ? C('REDIS_HOST') : '127.0.0.1',
'port' => C('REDIS_PORT') ? C('REDIS_PORT') : 6379,
'timeout' => C('REDIS_TIMEOUT') ? C('REDIS_TIMEOUT') : false,
'auth' => C('REDIS_AUTH') ? C('REDIS_AUTH'):null,//auth认证
'persistent' => C('REDIS_PERSISTENT') ? C('REDIS_PERSISTENT') : false,
);
}
$this->options = $options;
$this->options['expire'] = isset($options['expire'])? $options['expire'] : C('DATA_CACHE_TIME');
$this->options['prefix'] = isset($options['prefix'])? $options['prefix'] : C('DATA_CACHE_PREFIX');
$this->options['length'] = isset($options['length'])? $options['length'] : 0;
$func = $options['persistent'] ? 'pconnect' : 'connect';
$this->handler = new \Redis;
$options['timeout'] === false ?
$this->handler->$func($options['host'], $options['port']) :
$this->handler->$func($options['host'], $options['port'], $options['timeout']);

//Auth参数
if($this->options['auth']!=null)
{
$this->handler->auth($this->options['auth']);
}
}

/**
* 读取缓存
* @access public
* @param string $name 缓存变量名
* @return mixed
*/
public function get($name) {
N('cache_read',1);
$value = $this->handler->get($this->options['prefix'].$name);
$jsonData = json_decode( $value, true );
return ($jsonData === NULL) ? $value : $jsonData; //检测是否为JSON数据 true 返回JSON解析数组, false返回源数据
}

/**
* 写入缓存
* @access public
* @param string $name 缓存变量名
* @param mixed $value 存储数据
* @param integer $expire 有效时间(秒)
* @return boolean
*/
public function set($name, $value, $expire = null) {
N('cache_write',1);
if(is_null($expire)) {
$expire = $this->options['expire'];
}
$name = $this->options['prefix'].$name;
//对数组/对象数据进行缓存处理,保证数据完整性
$value = (is_object($value) || is_array($value)) ? json_encode($value) : $value;
if(is_int($expire)) {
$result = $this->handler->setex($name, $expire, $value);
}else{
$result = $this->handler->set($name, $value);
}
if($result && $this->options['length']>0) {
// 记录缓存队列
$this->queue($name);
}
return $result;
}

/**
* 删除缓存
* @access public
* @param string $name 缓存变量名
* @return boolean
*/
public function rm($name) {
return $this->handler->delete($this->options['prefix'].$name);
}

/**
* 清除缓存
* @access public
* @return boolean
*/
public function clear() {
return $this->handler->flushDB();
}

}

SESSION使用redis

复制以下内容到文本中,改名为Redis.class.php。
复制到ThinkPHP\Library\Think\Session\Driver\Redis.class.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
<?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 )
* +----------------------------------------------------------------------
*/

namespace Think\Session\Driver;

/**
* Redis Session驱动
*/
class Redis {

/**
* Redis句柄
*/
private $handler;
private $get_result;

public function __construct(){
if ( !extension_loaded('redis') ) {
E(L('_NOT_SUPPERT_').':redis');
}
if(empty($options)) {
$options = array (
'host' => C('REDIS_HOST') ? C('REDIS_HOST') : '127.0.0.1',
'port' => C('REDIS_PORT') ? C('REDIS_PORT') : 6379,
'timeout' => C('REDIS_TIMEOUT') ? C('REDIS_TIMEOUT') : false,
'persistent' => C('REDIS_PERSISTENT') ? C('REDIS_PERSISTENT') : false,
'auth' => C('REDIS_AUTH') ? C('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];
}
}
$this->options = $options;
$expire = C('SESSION_EXPIRE');
$this->options['expire'] = isset($expire) ? (int)$expire : (int)ini_get('session.gc_maxlifetime');;
$this->options['prefix'] = isset($options['prefix']) ? $options['prefix'] : C('SESSION_PREFIX');
$this->handler = new \Redis;
}

/**
* 连接Redis服务端
* @access public
* @param bool $is_master : 是否连接主服务器
*/
public function connect($is_master = true) {
if ($is_master) {
$i = 0;
} else {
$count = count($this->options['host']);
if ($count == 1) {
$i = 0;
} else {
$i = rand(1, $count - 1); //多个从服务器随机选择
}
}
$func = $this->options['persistent'] ? 'pconnect' : 'connect';
try {
if ($this->options['timeout'] === false) {
$result = $this->handler->$func($this->options['host'][$i], $this->options['port'][$i]);
if (!$result)
throw new \Think\Exception('Redis Error', 100);
} else {
$result = $this->handler->$func($this->options['host'][$i], $this->options['port'][$i], $this->options['timeout']);
if (!$result)
throw new \Think\Exception('Redis Error', 101);
}
if ($this->options['auth'][$i]) {
$result = $this->handler->auth($this->options['auth'][$i]);
if (!$result) {
throw new \Think\Exception('Redis Error', 102);
}
}
} catch ( \Exception $e ) {
exit('Error Message:'.$e->getMessage().'<br>Error Code:'.$e->getCode().'');
}
}

/**
+----------------------------------------------------------
* 打开Session
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $savePath
* @param mixed $sessName
+----------------------------------------------------------
*/
public function open($savePath, $sessName) {
return true;
}

/**
+----------------------------------------------------------
* 关闭Session
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
*/
public function close() {
if ($this->options['persistent'] == 'pconnect') {
$this->handler->close();
}
return true;
}

/**
+----------------------------------------------------------
* 读取Session
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $sessID
+----------------------------------------------------------
*/
public function read($sessID) {
$this->connect(0);
$this->get_result = $this->handler->get($this->options['prefix'].$sessID);
//延长有效期
$this->handler->expire($this->options['prefix'].$sessID,C('SESSION_EXPIRE'));
return $this->get_result;
}

/**
+----------------------------------------------------------
* 写入Session
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $sessID
* @param String $sessData
+----------------------------------------------------------
*/
public function write($sessID, $sessData) {
if (!$sessData || $sessData == $this->get_result) {
return true;
}
$this->connect(1);
$expire = $this->options['expire'];
$sessID = $this->options['prefix'].$sessID;
if(is_int($expire) && $expire > 0) {
$result = $this->handler->setex($sessID, $expire, $sessData);
$re = $result ? 'true' : 'false';
}else{
$result = $this->handler->set($sessID, $sessData);
$re = $result ? 'true' : 'false';
}
return $result;
}

/**
+----------------------------------------------------------
* 删除Session
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $sessID
+----------------------------------------------------------
*/
public function destroy($sessID) {
$this->connect(1);
return $this->handler->delete($this->options['prefix'].$sessID);
}

/**
+----------------------------------------------------------
* Session 垃圾回收
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $sessMaxLifeTime
+----------------------------------------------------------
*/
public function gc($sessMaxLifeTime) {
return true;
}

/**
+----------------------------------------------------------
* 打开Session
+----------------------------------------------------------
* @access public
+----------------------------------------------------------
* @param string $savePath
* @param mixed $sessName
+----------------------------------------------------------
*/
public function execute() {
session_set_save_handler(
array(&$this, "open"),
array(&$this, "close"),
array(&$this, "read"),
array(&$this, "write"),
array(&$this, "destroy"),
array(&$this, "gc")
);
}

public function __destruct() {
if ($this->options['persistent'] == 'pconnect') {
$this->handler->close();
}
session_write_close();
}

}

config 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//SESSION 配置
'SESSION_AUTO_START' => true, //是否开启session
'SESSION_TYPE' => 'Redis', //session 驱动
'SESSION_PREFIX' => 'sess_', //session前缀
'SESSION_EXPIRE' => '7200', //session有效期(单位:秒) 0表示永久缓存,当session被访问时,时间重新计算。

//缓存 配置
'DATA_CACHE_TYPE'=>'Redis',//默认动态缓存为Redis
'DATA_CACHE_PREFIX' => 'Redis_',//缓存前缀
'DATA_CACHE_TIME' => '0', //缓存时间 0为永久 当缓存被访问时,时间不重新计算

//Redis 配置
'REDIS_RW_SEPARATE' => true, //Redis读写分离 true 开启
'REDIS_HOST'=>'127.0.0.1', //redis服务器ip,多台用逗号隔开;读写分离开启时,第一台负责写,其它[随机]负责读;
'REDIS_PORT'=>'6379',//端口号
'REDIS_TIMEOUT'=>'30',//超时时间(秒)
'REDIS_PERSISTENT'=>false,//是否长连接 false=短连接
'REDIS_AUTH'=>'123456',//AUTH认证密码

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public function index(){
$test['a']='123';
$test['b']='1234';
$test['c']['a']='ca123';
$test['c']['b']='cb123';

S('test',$test);
$_SESSION['test']=$test;

echo "S缓存:</ br>";
dump(S('test'));
echo "SESSION:</ br>";
dump($_SESSION['test']);

exit;
}


使用redis管理工具查看