× 警告!旧版文档已经暂停维护,请查看新版文档。点击前往新版文档

订阅模式

本文档适用于4.2.13及以上版本,4.2.12及以下版本订阅模式存在BUG

订阅

与phpredis不同,subscribe/psubscribe为协程风格。

$redis = new Swoole\Coroutine\Redis();
$redis->connect('127.0.0.1', 6379);
if ($redis->subscribe(['channel1', 'channel2', 'channel3'])) // 或者使用psubscribe
{
    while ($msg = $redis->recv()) {
        // msg是一个数组, 包含以下信息
        // $type # 返回值的类型:显示订阅成功
        // $name # 订阅的频道名字 或 来源频道名字
        // $info  # 目前已订阅的频道数量 或 信息内容
        list($type, $name, $info) = $msg;
        if ($type == 'subscribe') // 或psubscribe
        {
            // 频道订阅成功消息,订阅几个频道就有几条
        }
        else if ($type == 'unsubscribe' && $info == 0) // 或punsubscribe
        {
            break; // 收到取消订阅消息,并且剩余订阅的频道数为0,不再接收,结束循环
        }
        else if ($type == 'message') // 若为psubscribe,此处为pmessage
        {
            // 打印来源频道名字
            var_dump($name);
            // 打印消息
            var_dump($info);
            // 处理消息
            // balabalaba....
            if ($need_unsubscribe) // 某个情况下需要退订
            {
                $redis->unsubscribe(); // 继续recv等待退订完成
            }
        }
    }
}

退订

退订使用unsubscribe/punsubscribe,$redis->unsubscribe(['channel1'])

此时$redis->recv()将会接收到一条取消订阅消息,若取消订阅多个频道,则会收到多条。

注意:退订后务必继续recv()到收到最后一条取消订阅消息($msg[2] == 0),收到此条消息后,才会退出订阅模式

En

$redis = new Swoole\Coroutine\Redis();
$redis->connect('127.0.0.1', 6379);
if ($redis->subscribe(['channel1', 'channel2', 'channel3'])) // or use psubscribe
{
    while ($msg = $redis->recv()) {
        // msg is an array containing the following information
        // $type # return type: show subscription success
        // $name # subscribed channel name or source channel name
        // $info  # the number of channels or information content currently subscribed
        list($type, $name, $info) = $msg;
        if ($type == 'subscribe') // or psubscribe
        {
            // channel subscription success message
        }
        else if ($type == 'unsubscribe' && $info == 0) // or punsubscribe
        {
            break; // received the unsubscribe message, and the number of channels remaining for the subscription is 0, no longer received, break the loop
        }
        else if ($type == 'message') // if it's psubscribe,here is pmessage
        {
            // print source channel name
            var_dump($name);
            // print message
            var_dump($info);
            // handle messsage
            if ($need_unsubscribe) // in some cases, you need to unsubscribe
            {
                $redis->unsubscribe(); // continue recv to wait unsubscribe finished
            }
        }
    }
}

  • wjbb1983

    要注意的是跨协程unsubscribe()不会中断recv(),想要实现跨协程中断要直接close(),这之后recv()会返回false

  • 18902449860

    能用swoole_event_add转为异步吗?求教,没调通