redis協(xié)程客戶端
雖然swoole有著自帶的協(xié)程客戶端,但是在生產(chǎn)環(huán)境中我們發(fā)現(xiàn)了一些問題:
swoole的redis客戶端并沒有完全支持redis的全部命令,比如geo搜索,還有事務(wù),特別是集群模式的redis,swoole客戶端并不支持。為此,我們決定用swoole的tcp客戶端實(shí)現(xiàn)一個(gè)完整版的redis客戶端。
目前,該redis客戶端組件,已經(jīng)支持除去腳本外的所有方法(目前支持了178個(gè)方法):
- 連接方法(connection)
- 集群方法(cluster)
- geohash
- 哈希(hash)
- 鍵(keys)
- 列表(lists)
- 訂閱/發(fā)布(pub/sub)
- 服務(wù)器(server)
- 字符串(string)
- 有序集合(sorted sets)
- 集合 (sets)
- 事務(wù) (transaction)
- 管道實(shí)現(xiàn) (pipe)
由于redis的命令較多,可能漏掉1,2個(gè)命令
組件要求
- php: >=7.1.0
- ext-swoole: ^4.4.0
- easyswoole/spl: ^1.2
安裝方法
composer require easyswoole/redis
倉庫地址
基本使用
redis 單機(jī)配置
redis 在實(shí)例化時(shí),需要傳入\EasySwoole\Redis\Config\RedisConfig
實(shí)例:
配置名 | 默認(rèn)參數(shù) | 說明 | 備注 |
---|---|---|---|
host | 127.0.0.1 | redis ip | |
port | 6379 | redis端口 | |
unixSocket | null | unixSocket文件路徑 | 此參數(shù)配置后,將忽略host,port參數(shù),直接通過UnixSocket連接.(>=1.3.0才可使用) |
auth | auth密碼 | ||
db | null | redis數(shù)據(jù)庫 | 當(dāng)db配置不等于null時(shí),在connect的時(shí)候會(huì)自動(dòng)select該配置 |
timeout | 3.0 | 超時(shí)時(shí)間 | |
reconnectTimes | 3 | 客戶端異常重連次數(shù) | |
serialize | SERIALIZE_NONE | 數(shù)據(jù)是否序列化 | 序列化參數(shù)有:SERIALIZE_NONE,SERIALIZE_PHP,SERIALIZE_JSON |
redis 單機(jī)配置示例
$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 集群在實(shí)例化時(shí),需要傳入\EasySwoole\Redis\Config\RedisConfig
實(shí)例:
$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
]);
集群配置先傳入一個(gè)ip,port的多維數(shù)組,再傳入其他配置項(xiàng),其他配置項(xiàng)和redis單機(jī)配置一致
需要注意,auth密碼需要集群所有節(jié)點(diǎn)相同,只支持一個(gè)密碼
redis單機(jī)使用示例
使用redis客戶端(需要協(xié)程環(huán)境)
<?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'));
});
回調(diào)事件
在redis
組件中,自定義了2個(gè)回調(diào)事件,用于代碼跟蹤調(diào)試,可在config中設(shè)置:
<?php
$redisConfig = new RedisConfig([
'host' => REDIS_HOST,
'port' => REDIS_PORT,
'auth' => REDIS_AUTH,
]);
// 命令執(zhí)行之前將調(diào)用
$redisConfig->onBeforeEvent(function ($commandName,$commandData){
var_dump ($commandName,$commandData);
});
//命令獲取到結(jié)果后將調(diào)用
$redisConfig->onAfterEvent(function ($commandName,$commandData,$result){
var_dump ($commandName,$commandData,$result);
});
回調(diào)事件支持事務(wù),pipe.
在pipe模式中,只有最后excePipe時(shí)才會(huì)調(diào)用回調(diào)事件.
異常處理
redis組件根據(jù)錯(cuò)誤的級(jí)別,區(qū)分了2種錯(cuò)誤信息
異常
當(dāng)redis連接失敗,無法和redis服務(wù)通信時(shí),將會(huì)拋出EasySwoole\Redis\Exception\RedisException
異常,例如配置錯(cuò)誤:
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']);//多了一個(gè)參數(shù),redis將會(huì)報(bào)語法錯(cuò)誤
var_dump($data);
}catch (\EasySwoole\Redis\Exception\RedisException $exception){
var_dump($exception->getMessage());
var_dump($exception->getRedisErrorCode());
var_dump($exception->getRedisErrorMsg());
}
});