Laravel系列-redis使用
Redis
Redis 是一个开源的 key-value 数据库。在某些场合上可以对关系型数据库进行很好的补充。Redis 的命令使用起来非常方便,例如对于字符串的存取
//存入字符串
127.0.0.1:6379> set name key
OK
//取出存入的字符串
127.0.0.1:6379> get name
"key"
更多的 Redis 相关的内容可以访问官网。
Laravel 中使用 Redis
Redis 可以支持诸多语言。例如 Java,Php,Ruby,Python 等。在 Laravel 中可以很方便的集成 Redis,只需要通过 Composer 安装一个扩展包就行:
"require": {
"predis/predis": "~1.0",
}
好了,然后就可以在 Laravel 中使用 Redis 了。可以将 Redis 当作队列来使用,也可以将 Redis 作为缓存来使用。
这些简单的用法在 Laravel 的官方文档中都可以找到很详细的文档。就不多说,今天要说的是使用过程当中的一个坑。
Redis 坑
Redis 中的发布/订阅是一个很棒的工具,有着很广的用处。但是找个特性在使用的过程中却是有些坑存在,看下面的代码:
Redis::subscribe(['test-channel'], function($message) {
echo $message;
});
Route::get('publish', function () {
// Route logic...
Redis::publish('test-channel', json_encode(['foo' => 'bar']));
});
上面的代码就是 订阅模式在 Laravel 中的使用,通过一个匿名的回调函数来接收发布的消息。这里要注意的是,Redis 的订阅的命令会在后台生成一个守护进程。而 Redis 连接服务器使用的是 Socket,所以如果按照 php 的默认配置,在60秒后就会自动断开连接,订阅就没有办法继续了。所以需要在这里加一个防止超时方法,例如下面:
ini_set('default_socket_timeout', -1); // 防止连接超时
Redis::subscribe(['test-channel'], function($message) {
echo $message;
});
Route::get('publish', function () {
// Route logic...
Redis::publish('test-channel', json_encode(['foo' => 'bar']));
});
除了上面的坑之外还有一个坑,依然看上面的代码,我做如下的修改:
ini_set('default_socket_timeout', -1); // 防止连接超时
Redis::subscribe(['test-channel'], function($message) {
Redis::set('name', $message);
});
Route::get('publish', function () {
// Route logic...
Redis::publish('test-channel', json_encode(['foo' => 'bar']));
});
如果按照上面的写法,则会报如下的错误:
exception 'Predis\Response\ServerException' with message 'ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / QUIT allowed in this context'
找个错误的原因是在回调函数的范围内使用了 Redis::set
方法,通过看 Github
上的 issue,发现 Redis::
生成的是同一个客户端,而在同一个客户端内,只能使用上面错误里面列出的几个命令。上面的代码里面,我使用了 Redis::set
命令,于是就报了上面的错误。解决找个问题的方法就是生成一个不同的 Redis
客户端,如下代码:
ini_set('default_socket_timeout', -1); // 防止连接超时
Redis::subscribe(['test-channel'], function($message) {
$redisClient = new Predis\Client();
$redisClient->set('name', $message);
});
Route::get('publish', function () {
// Route logic...
Redis::publish('test-channel', json_encode(['foo' => 'bar']));
});
通过上面的代码就可以解决那些问题了。
总之,Laravel 还是一个不错的框架的。