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

仓库地址

easyswoole/redis

基本使用

redis 单机配置

redis 在实例化时,需要传入\EasySwoole\Redis\Config\RedisConfig实例:

配置名默认参数说明备注
host127.0.0.1redis ip
port6379redis端口
unixSocketnullunixSocket文件路径此参数配置后,将忽略host,port参数,直接通过UnixSocket连接.(>=1.3.0才可使用)
authauth密码
dbnullredis数据库当db配置不等于null时,在connect的时候会自动select该配置
timeout3.0超时时间
reconnectTimes3客户端异常重连次数
serializeSERIALIZE_NONE数据是否序列化序列化参数有:SERIALIZE_NONE,SERIALIZE_PHP,SERIALIZE_JSON

redis 单机配置示例

  1. $config = new \EasySwoole\Redis\Config\RedisConfig([
  2. 'host' => '127.0.0.1',
  3. 'port' => '6379',
  4. 'auth' => 'easyswoole',
  5. 'db' => null,
  6. 'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_NONE
  7. ]);

redis集群配置

redis 集群在实例化时,需要传入\EasySwoole\Redis\Config\RedisConfig实例:

  1. $config = new \EasySwoole\Redis\Config\RedisClusterConfig([
  2. ['172.16.253.156', 9001],
  3. ['172.16.253.156', 9002],
  4. ['172.16.253.156', 9003],
  5. ['172.16.253.156', 9004],
  6. ], [
  7. 'auth' => '',
  8. 'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_PHP
  9. ]);

集群配置先传入一个ip,port的多维数组,再传入其他配置项,其他配置项和redis单机配置一致

需要注意,auth密码需要集群所有节点相同,只支持一个密码

redis单机使用示例

使用redis客户端(需要协程环境)

  1. <?php
  2. include "../vendor/autoload.php";
  3. go(function (){
  4. $redis = new \EasySwoole\Redis\Redis(new \EasySwoole\Redis\Config\RedisConfig([
  5. 'host' => '127.0.0.1',
  6. 'port' => '6379',
  7. 'auth' => 'easyswoole',
  8. 'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_NONE
  9. ]));
  10. var_dump($redis->set('a',1));
  11. var_dump($redis->get('a'));
  12. });

redis集群使用示例

  1. <?php
  2. include "../vendor/autoload.php";
  3. go(function () {
  4. $redis = new \EasySwoole\Redis\RedisCluster(new \EasySwoole\Redis\Config\RedisClusterConfig([
  5. ['172.16.253.156', 9001],
  6. ['172.16.253.156', 9002],
  7. ['172.16.253.156', 9003],
  8. ['172.16.253.156', 9004],
  9. ], [
  10. 'auth' => '',
  11. 'serialize' => \EasySwoole\Redis\Config\RedisConfig::SERIALIZE_PHP
  12. ]));
  13. var_dump($redis->set('a',1));
  14. var_dump($redis->get('a'));
  15. var_dump($redis->clusterKeySlot('a'));
  16. });

回调事件

redis组件中,自定义了2个回调事件,用于代码跟踪调试,可在config中设置:

  1. <?php
  2. $redisConfig = new RedisConfig([
  3. 'host' => REDIS_HOST,
  4. 'port' => REDIS_PORT,
  5. 'auth' => REDIS_AUTH,
  6. ]);
  7. // 命令执行之前将调用
  8. $redisConfig->onBeforeEvent(function ($commandName,$commandData){
  9. var_dump ($commandName,$commandData);
  10. });
  11. //命令获取到结果后将调用
  12. $redisConfig->onAfterEvent(function ($commandName,$commandData,$result){
  13. var_dump ($commandName,$commandData,$result);
  14. });

回调事件支持事务,pipe.
在pipe模式中,只有最后excePipe时才会调用回调事件.

异常处理

redis组件根据错误的级别,区分了2种错误信息

异常

当redis连接失败,无法和redis服务通信时,将会抛出EasySwoole\Redis\Exception\RedisException 异常,例如配置错误:

  1. 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
  2. Stack trace:
  3. #0 /www/easyswoole/tioncico_redis/src/Redis.php(579): EasySwoole\Redis\Redis->sendCommand(Array)
  4. #1 /www/easyswoole/tioncico_redis/tests/test.php(17): EasySwoole\Redis\Redis->get('a')
  5. #2 {main}
  6. thrown in /www/easyswoole/tioncico_redis/src/Redis.php on line 2866

接管异常

  1. go(function () {
  2. $redisConfig = new \EasySwoole\Redis\Config\RedisConfig();
  3. $redisConfig->setAuth('easyswoole');
  4. $redis = new \EasySwoole\Redis\Redis($redisConfig);
  5. try{
  6. $data = $redis->rawCommand(['set','a','1','1']);//多了一个参数,redis将会报语法错误
  7. var_dump($data);
  8. }catch (\EasySwoole\Redis\Exception\RedisException $exception){
  9. var_dump($exception->getMessage());
  10. var_dump($exception->getRedisErrorCode());
  11. var_dump($exception->getRedisErrorMsg());
  12. }
  13. });