MixPHP V2.1 Ecology: Swoole Coroutine Redis Subscriber

There is a Mix Redis Subscribe project in the OpenMix family bucket . This is a library that does not rely on phpredis extensions and directly parses the Redis protocol for subscription processing. Any Swoole framework can be used and can be widely used in WebSocket development. In MixPHP This library is also included by default in the skeleton.

Why develop

After the completion of MixPHP V2.1 development, I tried to develop a WebScoket service based on subscription mechanism. The service needs to dynamically switch subscription channels, but the subscription method of phpredis cannot achieve the following functions:

$redis = new \Redis();
$res   = $redis->pconnect('127.0.0.1', 6379, 0);
$redis->subscribe(['test'], function ($instance, $channelName, $message) {
    echo $channelName, "==>", $message, PHP_EOL;
});


  • Unable to know that the subscription was successful

In the above code, when subscribe is executed, the execution will be blocked, and the anonymous function will only be executed when there is a message, and the closure will not be executed when the subscription is successful, but when redis-cli executes the subscription, redis-server There is a reply to the subscription success message, so it is a design problem of phpredis.

  • Unable to dynamically subscribe to add channels

Since subscribe blocks execution, the code can only be executed in the callback when a message triggers the callback, so dynamically adding channels is also inoperable.

  • unsubscribe can only be executed in callbacks

Because of the blocking callback design above, if you need to cancel a channel, you can only operate it when a message comes, but the actual requirement is usually to cancel the channel at any time.

  • Cannot close connection in other coroutines

phpredis will throw an exception when trying to close the connection in other coroutines other than anonymous functions PHP Fatal error: Uncaught RedisException: read error on connection, which makes it impossible to close a redis connection in a subscription gracefully.

make wheels

When I learned that the redis protocol is a simple text protocol, I decided to abandon phpredis and build a useful subscription library myself. The new wheel has the following advantages:

  • Does not depend on phpredis extension
  • Smooth modification: Channels can be added or unsubscribed at any time to meet the needs of seamless channel switching.
  • Cross-coroutine safe shutdown: Subscriptions can be closed at any time.
  • Channel acquisition of messages: The encapsulation style of the library refers to the encapsulation of the golang language go-redis library, and the subscribed messages are acquired through the channel.
$sub = new \Mix\Redis\Subscribe\Subscriber('127.0.0.1', 6379, '', 5); // 连接失败将抛出异常
$sub->subscribe('foo', 'bar'); // 订阅失败将抛出异常

$chan = $sub->channel();
while (true) {
    $data = $chan->pop();
    if (empty($data)) { // 手动close与redis异常断开都会导致返回false
        if (!$sub->closed) {
            // redis异常断开处理
            var_dump('Redis connection is disconnected abnormally');
        }
        break;
    }
    var_dump($data);
}


Subscription message received:

object(Mix\Redis\Subscribe\Message)#8 (2) {
  ["channel"]=>
  string(2) "foo"
  ["payload"]=>
  string(4) "test"
}


{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324140454&siteId=291194637