redis订阅和发布
2016-02-29 10:41
495 查看
redis通过PUBLISH、SUBSCRIBE等命令实现了订阅与发布模式,这个功能有两种信息机制,分别是订阅\发布到频道、订阅\发布到模式。
订阅\发布到频道:
频道的订阅与信息发送。
redis的subscribe命令可以让客户端订阅任意数量的频道,每当有信息发送到被订阅的频道时,信息就会被发送给所有订阅指定频道的客户端。
作为例子,下图展示了频道
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-58f7b1f1f52b28f59291d194555fc9f4b1462a4c.svg)
当有新消息通过
PUBLISH 命令发送给频道
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-84c95abf88d6c0ac55b007da08805a4b9a582fdf.svg)
在后面的内容中,我们将探讨
SUBSCRIBE 和
PUBLISH 命令的实现,以及这套订阅与发布机制的运作原理。
订阅频道:
每个 Redis 服务器进程都维持着一个表示服务器状态的
其中,字典的键为正在被订阅的频道,字典的值则是一个链表,链表中保存了所有订阅这个频道的客户端。
比如说,在下图展示的这个
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-241c988b86bb9bed6bf26537e654baaab4eef77b.svg)
当客户端调用subscribe命令时,程序就将客户端和要订阅的频道在pubsub_channels字典中关联起来。
举个例子,如果客户端
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-cb250b1be4aaaedc9d5ddde113a80998d7f9c480.svg)
SUBSCRIBE 命令的行为可以用伪代码表示如下:
通过
发送信息到频道:
了解了pubsub_channels字典的结构后,解释publish命令的实现就简单了,当调用publish channel message命令,程序首先根据channel定位到字典的键,然后将信息发送给字典值链表中的所有客户端。
例如:如果客户端执行命令publish channel "helloword"那么订阅了这个频道的客户端都会接收到helloword这个消息。
publish命令的伪代码实现:
def PUBLISH (channel,message)
#遍历所有订阅该频道channel的客户端
for client in server.pubsub_channels[channelName]:
#将信息发送给这些客户端
send_message(client,message)
使用
UNSUBSCRIBE 命令可以退订指定的频道,这个命令执行的是订阅的反操作:它从
实例:在客户端实时响应的数据,每次返回三个字段:message,频道名称,接收到的信息。
服务端发送的数据:
模式的订阅与发布:
当使用publish命令发送信息到某个频道的时候,不仅所有订阅了该频道的客户端会收到信息,如果有某个模式和这个频道匹配的话,那么所有订阅这个频道的客户端也会收到信息。
下图展示了一个带有频道和模式的例子,其中
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-49c2b60cc3c2b52ec1623fbd8a9002eb6f335a54.svg)
当有信息发送到
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-3d1f513ee0718a326d53152b2b97f82977e38ad6.svg)
另一方面,如果接收到信息的是频道
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-ba8c4d4dd538464659aeb52d6c366f23ad3d0dc1.svg)
链表中的每个节点都包含一个
每当调用
作为例子,下图展示了一个包含两个模式的
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-b8d101c1b582531bce2b0daef87adbaf30ebc195.svg)
如果这时客户端
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-a84f3abf466ca19297faaa4e11d37f9257355c60.svg)
通过遍历整个
PUBLISH 命令进行的,在前面讲解频道的时候,我们给出了这样一段伪代码,说它定义了
PUBLISH 命令的行为:
但是,这段伪代码并没有完整描述
PUBLISH 命令的行为,因为
PUBLISH 除了将
完整描述
PUBLISH 功能的伪代码定于如下:
举个例子,如果 Redis 服务器的
![](http://redisbook.readthedocs.org/en/latest/_images/graphviz-a84f3abf466ca19297faaa4e11d37f9257355c60.svg)
那么当某个客户端发送信息
PUNSUBSCRIBE 命令可以退订指定的模式,这个命令执行的是订阅模式的反操作:程序会删除
当有新消息发送到频道时,程序遍历频道(键)所对应的(值)所有客户端,然后将消息发送到所有订阅频道的客户端上。
订阅模式的信息由服务器进程维持的
当有新消息发送到频道时,除了订阅频道的客户端会收到消息之外,所有订阅了匹配频道的模式的客户端,也同样会收到消息。
退订频道和退订模式分别是订阅频道和订阅模式的反操作。
转载:http://redisbook.readthedocs.org/en/latest/feature/pubsub.html#id6
订阅\发布到频道:
频道的订阅与信息发送。
redis的subscribe命令可以让客户端订阅任意数量的频道,每当有信息发送到被订阅的频道时,信息就会被发送给所有订阅指定频道的客户端。
作为例子,下图展示了频道
channel1,以及订阅这个频道的三个客户端 ——
client2、
client5和
client1之间的关系:
当有新消息通过
PUBLISH 命令发送给频道
channel1时,这个消息就会被发送给订阅它的三个客户端:
在后面的内容中,我们将探讨
SUBSCRIBE 和
PUBLISH 命令的实现,以及这套订阅与发布机制的运作原理。
订阅频道:
每个 Redis 服务器进程都维持着一个表示服务器状态的
redis.h/redisServer结构,结构的
pubsub_channels属性是一个字典,这个字典就用于保存订阅频道的信息。
其中,字典的键为正在被订阅的频道,字典的值则是一个链表,链表中保存了所有订阅这个频道的客户端。
比如说,在下图展示的这个
pubsub_channels示例中,
client2、
client5和
client1就订阅了
channel1,而其他频道也分别被别的客户端所订阅:
当客户端调用subscribe命令时,程序就将客户端和要订阅的频道在pubsub_channels字典中关联起来。
举个例子,如果客户端
client10086执行命令
SUBSCRIBE channel1 channel2 channel3,那么前面展示的
pubsub_channels将变成下面这个样子:
SUBSCRIBE 命令的行为可以用伪代码表示如下:
def SUBSCRIBE(client, channels): # 遍历所有输入频道 for channel in channels: # 将客户端添加到链表的末尾 redisServer.pubsub_channels[channel].append(client)
通过
pubsub_channels字典,程序只要检查某个频道是否为字典的键,就可以知道该频道是否正在被客户端订阅;只要取出某个键的值,就可以得到所有订阅该频道的客户端的信息。
发送信息到频道:
了解了pubsub_channels字典的结构后,解释publish命令的实现就简单了,当调用publish channel message命令,程序首先根据channel定位到字典的键,然后将信息发送给字典值链表中的所有客户端。
例如:如果客户端执行命令publish channel "helloword"那么订阅了这个频道的客户端都会接收到helloword这个消息。
publish命令的伪代码实现:
def PUBLISH (channel,message)
#遍历所有订阅该频道channel的客户端
for client in server.pubsub_channels[channelName]:
#将信息发送给这些客户端
send_message(client,message)
使用
UNSUBSCRIBE 命令可以退订指定的频道,这个命令执行的是订阅的反操作:它从
pubsub_channels字典的给定频道(键)中,删除关于当前客户端的信息,这样被退订频道的信息就不会再发送给这个客户端。
实例:在客户端实时响应的数据,每次返回三个字段:message,频道名称,接收到的信息。
服务端发送的数据:
模式的订阅与发布:
当使用publish命令发送信息到某个频道的时候,不仅所有订阅了该频道的客户端会收到信息,如果有某个模式和这个频道匹配的话,那么所有订阅这个频道的客户端也会收到信息。
下图展示了一个带有频道和模式的例子,其中
tweet.shop.*模式匹配了
tweet.shop.kindle频道和
tweet.shop.ipad频道,并且有不同的客户端分别订阅它们三个:
当有信息发送到
tweet.shop.kindle频道时,信息除了发送给
clientX和
clientY之外,还会发送给订阅
tweet.shop.*模式的
client123和
client256:
另一方面,如果接收到信息的是频道
tweet.shop.ipad,那么
client123和
client256同样会收到信息:
订阅模式
redisServer.pubsub_patterns属性是一个链表,链表中保存着所有和模式相关的信息:
struct redisServer { // ... list *pubsub_patterns; // ... };
链表中的每个节点都包含一个
redis.h/pubsubPattern结构:
typedef struct pubsubPattern { redisClient *client; robj *pattern; } pubsubPattern;
client属性保存着订阅模式的客户端,而
pattern属性则保存着被订阅的模式。
每当调用
PSUBSCRIBE命令订阅一个模式时,程序就创建一个包含客户端信息和被订阅模式的
pubsubPattern结构,并将该结构添加到
redisServer.pubsub_patterns链表中。
作为例子,下图展示了一个包含两个模式的
pubsub_patterns链表,其中
client123和
client256都正在订阅
tweet.shop.*模式:
如果这时客户端
client10086执行
PSUBSCRIBE broadcast.list.*,那么
pubsub_patterns链表将被更新成这样:
通过遍历整个
pubsub_patterns链表,程序可以检查所有正在被订阅的模式,以及订阅这些模式的客户端。
发送信息到模式
发送信息到模式的工作也是由PUBLISH 命令进行的,在前面讲解频道的时候,我们给出了这样一段伪代码,说它定义了
PUBLISH 命令的行为:
def PUBLISH(channel, message): # 遍历所有订阅频道 channel 的客户端 for client in server.pubsub_channels[channel]: # 将信息发送给它们 send_message(client, message)
但是,这段伪代码并没有完整描述
PUBLISH 命令的行为,因为
PUBLISH 除了将
message发送到所有订阅
channel的客户端之外,它还会将
channel和
pubsub_patterns中的模式进行对比,如果
channel和某个模式匹配的话,那么也将
message发送到订阅那个模式的客户端。
完整描述
PUBLISH 功能的伪代码定于如下:
def PUBLISH(channel, message): # 遍历所有订阅频道 channel 的客户端 for client in server.pubsub_channels[channel]: # 将信息发送给它们 send_message(client, message)
# 取出所有模式,以及订阅模式的客户端
for pattern, client in server.pubsub_patterns:
# 如果 channel 和模式匹配
if match(channel, pattern):
# 那么也将信息发给订阅这个模式的客户端
send_message(client, message)
举个例子,如果 Redis 服务器的
pubsub_patterns状态如下:
那么当某个客户端发送信息
"Amazon Kindle, $69."到
tweet.shop.kindle频道时,除了所有订阅了
tweet.shop.kindle频道的客户端会收到信息之外,客户端
client123和
client256也同样会收到信息,因为这两个客户端订阅的
tweet.shop.*模式和
tweet.shop.kindle频道匹配。
退订模式
使用PUNSUBSCRIBE 命令可以退订指定的模式,这个命令执行的是订阅模式的反操作:程序会删除
redisServer.pubsub_patterns链表中,所有和被退订模式相关联的
pubsubPattern结构,这样客户端就不会再收到和模式相匹配的频道发来的信息。
小结
订阅信息由服务器进程维持的redisServer.pubsub_channels字典保存,字典的键为被订阅的频道,字典的值为订阅频道的所有客户端。
当有新消息发送到频道时,程序遍历频道(键)所对应的(值)所有客户端,然后将消息发送到所有订阅频道的客户端上。
订阅模式的信息由服务器进程维持的
redisServer.pubsub_patterns链表保存,链表的每个节点都保存着一个
pubsubPattern结构,结构中保存着被订阅的模式,以及订阅该模式的客户端。程序通过遍历链表来查找某个频道是否和某个模式匹配。
当有新消息发送到频道时,除了订阅频道的客户端会收到消息之外,所有订阅了匹配频道的模式的客户端,也同样会收到消息。
退订频道和退订模式分别是订阅频道和订阅模式的反操作。
转载:http://redisbook.readthedocs.org/en/latest/feature/pubsub.html#id6
相关文章推荐
- redis的基本操作
- CentOS上安装redis
- 利用tomcat-redis-session-manager解决tomcat的分布式session问题
- Jedis学习使用(java操作redis)
- redis主从配置sentinel模式springboot访问
- redis的各种数据类型
- redis安装
- redis配置文件redis.conf参数说明
- Redis学习笔记
- Redis 常见的性能问题和解决方法
- redis主从配置
- redis主从配置
- ubuntu中pip安装redis-py及pip的使用
- Redis3.0与Jedis2.7.2 客户端与Spring整合
- Redis集群搭建之Redis Cluster实践
- redis的安装
- 【redis 基础篇二】redis安装-Linux服务
- 【redis 基础篇一】redis初识
- redis的hGetAll函数的性能问题(记Redis那坑人的HGETALL)
- redis安装步骤