redis協程客戶端
雖然swoole有著自帶的協程客戶端,但是在生產環境中我們發現了一些問題:
swoole的redis客戶端并沒有完全支持redis的全部命令,比如geo搜索,還有事務,特別是集群模式的redis,swoole客戶端并不支持。為此,我們決定用swoole的tcp客戶端實現一個完整版的redis客戶端。
目前,該redis客戶端組件,已經支持除去腳本外的所有方法(目前支持了178個方法):
- 連接方法(connection)
- 集群方法(cluster)
- geohash
- 哈希(hash)
- 鍵(keys)
- 列表(lists)
- 訂閱/發布(pub/sub)
- 服務器(server)
- 字符串(string)
- 有序集合(sorted sets)
- 集合 (sets)
- 事務 (transaction)
- 管道實現 (pipe)
由于redis的命令較多,可能漏掉1,2個命令
組件要求
- php: >=7.1.0
- ext-swoole: ^4.4.0
- easyswoole/spl: ^1.2
安裝方法
composer require easyswoole/redis
倉庫地址
基本使用
redis 單機配置
redis 在實例化時,需要傳入\EasySwoole\Redis\Config\RedisConfig
實例:
配置名 | 默認參數 | 說明 | 備注 |
---|---|---|---|
host | 127.0.0.1 | redis ip | |
port | 6379 | redis端口 | |
unixSocket | null | unixSocket文件路徑 | 此參數配置后,將忽略host,port參數,直接通過UnixSocket連接.(>=1.3.0才可使用) |
auth | auth密碼 | ||
db | null | redis數據庫 | 當db配置不等于null時,在connect的時候會自動select該配置 |
timeout | 3.0 | 超時時間 | |
reconnectTimes | 3 | 客戶端異常重連次數 | |
serialize | SERIALIZE_NONE | 數據是否序列化 | 序列化參數有:SERIALIZE_NONE,SERIALIZE_PHP,SERIALIZE_JSON |
redis 單機配置示例
$config = new \EasySwoole\Redis\Config\RedisConfig([
'host' => '127.0.0.1',
'port' => '6379',
'auth' => 'easyswoole',
'db' => null,
'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_NONE
]);
redis集群配置
redis 集群在實例化時,需要傳入\EasySwoole\Redis\Config\RedisConfig
實例:
$config = new \EasySwoole\Redis\Config\RedisClusterConfig([
['172.16.253.156', 9001],
['172.16.253.156', 9002],
['172.16.253.156', 9003],
['172.16.253.156', 9004],
], [
'auth' => '',
'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_PHP
]);
集群配置先傳入一個ip,port的多維數組,再傳入其他配置項,其他配置項和redis單機配置一致
需要注意,auth密碼需要集群所有節點相同,只支持一個密碼
redis單機使用示例
使用redis客戶端(需要協程環境)
<?php
include "../vendor/autoload.php";
go(function (){
$redis = new \EasySwoole\Redis\Redis(new \EasySwoole\Redis\Config\RedisConfig([
'host' => '127.0.0.1',
'port' => '6379',
'auth' => 'easyswoole',
'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_NONE
]));
var_dump($redis->set('a',1));
var_dump($redis->get('a'));
});
redis集群使用示例
<?php
include "../vendor/autoload.php";
go(function () {
$redis = new \EasySwoole\Redis\RedisCluster(new \EasySwoole\Redis\Config\RedisClusterConfig([
['172.16.253.156', 9001],
['172.16.253.156', 9002],
['172.16.253.156', 9003],
['172.16.253.156', 9004],
], [
'auth' => '',
'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_PHP
]));
var_dump($redis->set('a',1));
var_dump($redis->get('a'));
var_dump($redis->clusterKeySlot('a'));
});
回調事件
在redis
組件中,自定義了2個回調事件,用于代碼跟蹤調試,可在config中設置:
<?php
$redisConfig = new RedisConfig([
'host' => REDIS_HOST,
'port' => REDIS_PORT,
'auth' => REDIS_AUTH,
]);
// 命令執行之前將調用
$redisConfig->onBeforeEvent(function ($commandName,$commandData){
var_dump ($commandName,$commandData);
});
//命令獲取到結果后將調用
$redisConfig->onAfterEvent(function ($commandName,$commandData,$result){
var_dump ($commandName,$commandData,$result);
});
回調事件支持事務,pipe.
在pipe模式中,只有最后excePipe時才會調用回調事件.
異常處理
redis組件根據錯誤的級別,區分了2種錯誤信息
異常
當redis連接失敗,無法和redis服務通信時,將會拋出EasySwoole\Redis\Exception\RedisException
異常,例如配置錯誤:
PHP Fatal error: Uncaught EasySwoole\Redis\Exception\RedisException: connect to redis host 127.0.0.1:6379 fail after retry 4 times in /www/easyswoole/tioncico_redis/src/Redis.php:2866
Stack trace:
#0 /www/easyswoole/tioncico_redis/src/Redis.php(579): EasySwoole\Redis\Redis->sendCommand(Array)
#1 /www/easyswoole/tioncico_redis/tests/test.php(17): EasySwoole\Redis\Redis->get('a')
#2 {main}
thrown in /www/easyswoole/tioncico_redis/src/Redis.php on line 2866
接管異常
go(function () {
$redisConfig = new \EasySwoole\Redis\Config\RedisConfig();
$redisConfig->setAuth('easyswoole');
$redis = new \EasySwoole\Redis\Redis($redisConfig);
try{
$data = $redis->rawCommand(['set','a','1','1']);//多了一個參數,redis將會報語法錯誤
var_dump($data);
}catch (\EasySwoole\Redis\Exception\RedisException $exception){
var_dump($exception->getMessage());
var_dump($exception->getRedisErrorCode());
var_dump($exception->getRedisErrorMsg());
}
});