频道发布与消息订阅

1.概念


image.png

2.注意事项
1.生产者publish消息时打开一个连接,publish后连接可以立即关闭
2.channel只接收publish发送的消息,自身不存储消息,如果channel没有被订阅,则消息丢弃
3.订阅的消费者需要一直在线,阻塞获取消息,连接断开表示立即退订

3.使用rawCommand命令实现发布订阅
rawCommand是php-redis扩展中提供的命令,可以向redis发送任何原生的命令

1.消费者订阅Subscribe.php
消费者需要创建redis长连接,并且设置set_time_limit和default_socket_timeout,以确保阻塞获取消息过程php不超时,socket连接不超时

<?php
/**
 * Created by PhpStorm.
 * User: jmsite.cn
 * Date: 2019/1/23
 * Time: 11:29
 */
//设置php脚本执行时间
set_time_limit(0);
//设置socket连接超时时间
ini_set('default_socket_timeout', -1);
//声明测试频道名称
$channelName = "testPubSub";
$channelName2 = "testPubSub2";
try {
    $redis = new Redis();
    //建立一个长链接
    $redis->pconnect('192.168.75.132', 6379);
    //阻塞获取消息
    while (true){
        //构建命令参数
        $param = array('subscribe', $channelName, $channelName2);
        //使用call_user_func_array回调执行命令
        $ret = call_user_func_array(array($redis, 'rawCommand'), $param);
        //如果结果是消息结构
        if (isset($ret[0]) && $ret[0] == 'message'){
            //输出消息频道和消息内容
            echo "channel:".$ret[1].",message:".$ret[2]."\n";
        } else {
            //没有消息休眠1秒
            sleep(1);
        }
    }
} catch (Exception $e){
    echo $e->getMessage();
}

2.生产者发送消息Publish.php

<?php
/**
 * Created by PhpStorm.
 * User: jmsite.cn
 * Date: 2019/1/23
 * Time: 11:59
 */
$channelName = "testPubSub";
$channelName2 = "testPubSub2";
//向指定频道发送消息
try {
    $redis = new Redis();
    $redis->connect('192.168.75.132', 6379);
    for ($i=0;$i<5;$i++){
        $data = array('key' => 'key'.$i, 'data' => 'testdata');
        $param = array('publish', $channelName, json_encode($data));
        $ret = call_user_func_array(array($redis, 'rawCommand'), $param);
        print_r($ret);
    }
} catch (Exception $e){
    echo $e->getMessage();
}

3.执行消费者订阅,开始阻塞获取消息php Subscribe.php
4.执行生产者,开始发送消息php Publish.php

php .\Publish.php
22222
#返回执行结果:频道的订阅数量

查看消费者终端

php .\Subscribe.php
channel:testPubSub,message:{"key":"key0","data":"testdata"}
channel:testPubSub,message:{"key":"key1","data":"testdata"}
channel:testPubSub,message:{"key":"key2","data":"testdata"}
channel:testPubSub,message:{"key":"key3","data":"testdata"}
channel:testPubSub,message:{"key":"key4","data":"testdata"}

消费者获取到了生产者发送的消息。

4.直接使用php-redis扩展提供的方法实现发布订阅

1.消费者订阅Subscribe.php

<?php
/**
 * Created by PhpStorm.
 * User: jmsite.cn
 * Date: 2019/1/23
 * Time: 11:29
 */
//设置php脚本执行时间
set_time_limit(0);
//设置socket连接超时时间
ini_set('default_socket_timeout', -1);
//声明测试频道名称
$channelName = "testPubSub";
$channelName2 = "testPubSub2";
try {
    $redis = new Redis();
    //建立一个长链接
    $redis->pconnect('192.168.75.132', 6379);
    //阻塞获取消息
    $redis->subscribe(array($channelName, $channelName2), function ($redis, $chan, $msg){
        echo "channel:".$chan.",message:".$msg."\n";
    });
} catch (Exception $e){
    echo $e->getMessage();
}

2.生产者发送消息Publish.php

<?php
/**
 * Created by PhpStorm.
 * User: jmsite.cn
 * Date: 2019/1/23
 * Time: 11:59
 */
$channelName = "testPubSub";
$channelName2 = "testPubSub2";
//向指定频道发送消息
try {
    $redis = new Redis();
    $redis->connect('192.168.75.132', 6379);
    for ($i=0;$i<5;$i++){
        $data = array('key' => 'key'.$i, 'data' => 'testdata');
        $ret = $redis->publish($channelName, json_encode($data));
        print_r($ret);
    }
} catch (Exception $e){
    echo $e->getMessage();
}

3.执行消费者订阅,开始阻塞获取消息php Subscribe.php
4.执行生产者,开始发送消息php Publish.php

php .\Publish.php
22222
#返回执行结果:频道的订阅数量

查看消费者终端

php .\Subscribe.php
channel:testPubSub,message:{"key":"key0","data":"testdata"}
channel:testPubSub,message:{"key":"key1","data":"testdata"}
channel:testPubSub,message:{"key":"key2","data":"testdata"}
channel:testPubSub,message:{"key":"key3","data":"testdata"}
channel:testPubSub,message:{"key":"key4","data":"testdata"}

消费者同样获取到了生产者发送的消息。
退订和查看活动channel命令与生产者和消费者类似,只是参数不同而已。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容