Redis发布预订使用总结:
Redis发布订阅机制是一种消息通信机制,发布者发送消息,订阅者接收消息,而订阅者可以接收任意数量的频道信息,发布者也可以发布任意数量频道信息。而发布者不需要知道接受者是谁,同时订阅者也不需要知道接受的是哪个发布者发布的消息,这种发布者和订阅者的解耦合可以带来更大的扩展性和更加动态的网络拓扑。
· 工作原理
· 如何使用
· 消息格式
· 频道匹配
· 拓展使用
1、工作原理
NOTE:
如上图所示,发布者发送消息,订阅者接收消息,而订阅者可以接收任意数量的频道信息,发布者也可以发布任意数量频道信息。
2、如何使用
A、创建发布者和订阅者沟通的频道
127.0.0.1:6379> subscribe redisChannel
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChannel"
3) (integer) 1
B、打开另一个客户端,针对频道发消息
127.0.0.1:6379> publish redisChannel "This is a message for testingthe use of redis pub/scribe"
(integer) 1
127.0.0.1:6379> publish redisChannel "Please come on,you willverify the pub/scribe"
(integer) 1
C、订阅者成功从频道获取消息
127.0.0.1:6379> subscribe redisChannel
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "redisChannel"
3) (integer) 1
1) "message"
2) "redisChannel"
3) "This is a message for testing the use of redis pub/scribe"
1) "message"
2) "redisChannel"
3) "Please come on,you will verify the pub/scribe"
当然,我们也可以使用unsubscribe退订频道,punsubscribe退订所有给定模式频道,psubscribe订阅多个给定频道。
3、消息格式
A、格式
Redis的Pub/Sub常被用来作为推送消息使用,那么一个消息在Pub/Sub中的格式是由三个元素构成:消息类型、沟通频道及频道数量,如果消息类型是message,那么第三个元素对应的元素是具体的消息内容,对应关系如下:
第1个元素 | 第2个元素 | 第3个元素 |
subscribe | 订阅的频道 | 频道的数量 |
unsubscribe | 取消订阅的频道 | 频道的数量,为0时,代表不再订阅任何频道消息。 |
message | 消息来源的频道 | 具体消息内容 |
另外,Redis的Pub/Sub机制,是在客户端和服务器端的交互通信,所以它也需要遵循Redis的通信协议来规范通信的内容,只是不需要使用\r\n结尾,如下所示:
SUBSCRIBE channel "*3 $9 subscribe $7channel :1"
NOTE:
*2->代表两个元素;
$9->代表频道长度;
1 ->代表频道个数;
B、验证
首先,创建并订阅频道:
其次,针对频道发布消息:
最后,我们查看下客户端结果:
从上面的验证过程,我们了解到,客户端收到的结果消息格式:
"*3 $7 message $7 channel $5 Hello
另外,我们也可以取消频道订阅:
4、频道匹配
A、匹配
Redis的Pub/Sub支持频道匹配,也就是客户端可以订阅匹配的频道名字,以便接收到所有匹配的频道的消息,同理也可以取消所有匹配的频道消息的接受。
例如:
PSUBSCRIBE msg.*
也就是匹配或接受来自频道msg.1001,msg.1002,msg.bak系列的消息。
例如:
PUNSUBSCRIBE msg.*
也就是取消接受来自频道msg.1001,msg.1002,msg.bak系列的消息(只针对当前客户端的访问有效)。
B、验证
首先,创建频道匹配并监听事件:
其次,发布者发布多个消息:
最后,查看客户端结果显示:
从结果图中,我们看到频道匹配正常,因为只有在发布最后一条消息,即msgbk.100时,客户端并没有接收到消息,因为该频道不符合msg.*的匹配规则,所以接受不到。同样的,我们也可以使用PUNSUBCRIBE取消,这里不再赘述。
这里的消息格式如下:
第1个元素:频道匹配规则,如:msg.*;
第2个元素:来源的频道名,如:msg.1001;
第3个元素:消息的内容,如:Hello;
NOTE:
有的时候,客户端可以多次接受同一个消息,因为它订阅的频道匹配同时匹配到了同一个消息发布,这对这个情况,需要结合业务需求,如果业务需求不允许这种情况发生,最好在定制频道匹配时,使用能唯一标志匹配规则的标志,如用户的ID等。
5、拓展使用
Redis的Pub/Sub很适合实时消息功能实现,比如,实时的聊天系统(包括单聊和群聊),这个需求在一些电商(比如:天猫商城等)使用的比较多。当然,这里只实现两个模拟用户的终端通信的功能,其它辅助功能,比如,页面展示,数据存储以及其它细节等这里不做介绍,具体如下:
A、PHP脚本
<?php
// 参数说明
// $argv[1]:频道,$argv[2]:角色,$argv[3]:内容(发布者)
$redis = new \Redis();
$redis->connect('127.0.0.1',6379);
// 用户ID作为订阅频道
$userID = $argv[1];
$channel = 'channel_'.$userID;
if($argv[2] == 'sub') {
// 单一的频道订阅消息
// 定义并调用回调函数
$redis->subscribe(array($channel),function($redis,
$channelName,$message) {
echo$channelName,"==>",$message,PHP_EOL;
});
} else {
// 单一的频道发布消息
$msg = $argv[3];
$pubs =$redis->publish($channel,$msg);
if('1'== $pubs) {
echo '消息发布成功,发布的频道:'.$channel;
} else {
echo '消息发布失败,发布的频道:'.$channel;
}
}
?>
B、访问执行
首先,作为订阅者角色:
$ php ./redis_pubsub.php 1001 'sub'
其次,作为发布者角色:
$php ./redis_pubsub.php 1001 'pub' '你好吗?'
结果显示:
从截图可以看出,订阅者接收到发布者的消息。
NOTE:
因为PHP的拓展中使用Redis的pub/sub机制,所以Redis默认使用php.ini中的默认超时时间设置:default_socket_time,默认为60,如果订阅者阻塞等待超过这个时间,Redis就会返回RedisException异常,告诉你访问超时。解决的方案有两种,一种是将超时时间设置大些;另一种,则是通过触发点击等前段事件,如,发消息时,重新订阅频道即可解决。
技术讨论群:
489451956(新)