easy-swoole / easyswoole

swoole,easyswoole,swoole framework
https://www.easyswoole.com/
Apache License 2.0
4.74k stars 509 forks source link

在 redis 订阅里 如果调用了 unsubscribe , 会导致subscribe阻塞函数结束, 后面都收不到想要订阅的消息了 #394

Open fuzhufang opened 4 years ago

fuzhufang commented 4 years ago

php7.2.24 swoole 版本: 4.4.19 es 版本: 3.3.7

发布信息 $redis = new \EasySwoole\Redis\Redis(new \EasySwoole\Redis\Config\RedisConfig([...])); $data = $redis->pubSub('CHANNELS'); var_dump($data); $channel = 'C1'; $data = $redis->publish($channel, "向 $channel 发送"); var_dump($data, $channel);

订阅协程 情况一: go (function () use ($workerId) { $redis = new \EasySwoole\Redis\Redis(new \EasySwoole\Redis\Config\RedisConfig([...])); echo "开始监听订阅...........\n"; $redis->subscribe(function (\EasySwoole\Redis\Redis $redis, $pattern, $str) use ($workerId) { echo "worker=$workerId \n"; var_dump($pattern,$str); //$data = $redis->unsubscribe('XYZ'); //var_dump($data); }, 'C1', 'C2'); echo "收到订阅, 过了 subscribe 阻塞了 \n"; }); } 上面可以一直接收 发布到 C1 的消息, 并且不会打印 "收到订阅, 过了 subscribe 阻塞了 \n"

情况二: go (function () use ($workerId) { $redis = new \EasySwoole\Redis\Redis(new \EasySwoole\Redis\Config\RedisConfig([...])); echo "开始监听订阅...........\n"; $redis->subscribe(function (\EasySwoole\Redis\Redis $redis, $pattern, $str) use ($workerId) { echo "worker=$workerId \n"; var_dump($pattern,$str); $data = $redis->unsubscribe('XYZ'); var_dump($data); }, 'C1', 'C2'); echo "收到订阅, 过了 subscribe 阻塞了 \n"; }); } 执行了 unsubscribe('XYZ') 后 收到一次 发布C1的消息后, 会打印 "收到订阅, 过了 subscribe 阻塞了 \n" 以后再不能收到 C1 发布的消息了.

现在的问题是, 取消订阅的是 XYZ, 不是C1, 为什么不能继续接收C1的订阅呢?

rayswoole commented 4 years ago

推荐基于phpredis的连接池,配置文件直接写在mainServerCreate里面

Rhilip commented 4 years ago

推荐基于phpredis的连接池,配置文件直接写在mainServerCreate里面

我也觉得easyswoole/redis-pool的实现过于繁琐,你的能否考虑通过 phpdoc的 @method 注释来提供IDE支持?

longx1001 commented 4 years ago

推荐基于phpredis的连接池,配置文件直接写在mainServerCreate里面

我也觉得easyswoole/redis-pool的实现过于繁琐,你的能否考虑通过 phpdoc的 @method 注释来提供IDE支持?

Redis::getInstance() 写法带IDE提示,至于静态写法,由于phpredis的methed比较多,而且我为了符合psr的cache规范,在facade\redis里面的部分方法与phpredis重名, 所以没有写