• PUBLISH,SUBSCRIBE,等命令实现订阅与发布

    • 订阅/发布到频道
    • 订阅/发布到模式
 
频道的订阅与信息发送

 
订阅subscribe,可以让客户端订阅任意数量的频道,
每当有新信息发送到被订阅的频道时,信息就会被发送给所有订阅指定频道的客户端:
 

 
当有新消息通过publish命令发送给频道channel1时,这个消息就会被发送给订阅它的三个客户端:

 
订阅频道
每个 Redis 服务器进程都维持着一个表示服务器状态的 redis.h/redisServer 结构,结构的
pubsub_channels 属性是一个字典,这个字典就用于保存订阅频道的信息:
struct redisServer {
// ...
dict *pubsub_channels;
// ...
};

  

其中字典的键为正在被订阅的频道,而字典的值则是一个链表,链表中保存了所有订阅这个频道的客户端。
例如:
 

当客户端调用subscribe命令时,程序将客户端和要订阅的频道在pubsub_channels字典中关联起来。
举个例子,如果客户端 client10086 执行命令 SUBSCRIBE channel1 channel2 channel3 ,
那么前面展示的 pubsub_channels 将变成下面这个样子:
 

发送信息到频道
当调用 PUBLISH channel message 命令,程序首先根据 channel 定位到字典的键,然后将信息发
送给字典值链表中的所有客户端。
 
如果某个客户端执行命令
PUBLISH channel1 "hello moto" ,上图中那么 client2 、 client5 ,client1,client10086 4个客户端都将接收到 "hello moto"
 
退订频道
UNSUBSCRIBE 命令可以退订指定的频道, 它从pubsub_channels 字典的给定频道(键)中,删除关于当前客户端的信息,这样被退订频道的信息就不会再发送给这个客户端。
 
模式的订阅与信息发送

当使用 PUBLISH 命令发送信息到某个频道时,不仅所有订阅该频道的客户端会收到信息,如
果有某个/某些模式和这个频道匹配的话,那么所有订阅这个/这些频道的客户端也同样会收到
信息。
 
带频道和模式的例子, 其中 tweet.shop.* 模式匹配了 tweet.shop.kindle
频道和 tweet.shop.ipad 频道,并且有不同的客户端分别订阅它们三个:
 

当有信息发送到 tweet.shop.kindle 频道时,信息除了发送给 clientX 和 clientY 之外,还
会发送给订阅 tweet.shop.* 模式的 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 链表中。
 

 
如果这时客户端 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) # 取出所有模式,以及订阅模式的客户端
for pattern, client in server.pubsub_patterns: # 如果 channel 和模式匹配
if match(channel, pattern): # 那么也将信息发给订阅这个模式的客户端
send_message(client, message)

  

退订模式
使用 PUNSUBSCRIBE 命令可以退订指定的模式,这个命令执行的是订阅模式的反操作:程序
会删除 redisServer.pubsub_patterns 链表中,所有和被退订模式相关联的 pubsubPattern
结构,这样客户端就不会再收到和模式相匹配的频道发来的信息。
 
小结
  • 订阅信息由服务器进程维持的 redisServer.pubsub_channels 字典保存,

    • 字典的键为被订阅的频道,字典的值为订阅频道的所有客户端。
  • 当有新消息发送到频道时,程序遍历频道(键)所对应的(值)所有客户端,
    • 然后将消息发送到所有订阅频道的客户端上。
  • 订阅模式的信息由服务器进程维持的 redisServer.pubsub_patterns 链表保存,
    • 链表的每个节点都保存着一个pubsubPattern结构,结构中保存着被订阅的模式,
    • 以及订阅该模式的客户端。程序通过遍历链表来查找某个频道是否和某个模式匹配。
  • 当有新消息发送到频道时,除了订阅频道的客户端会收到消息之外,
    • 所有订阅了匹配频、道的模式的客户端,也同样会收到消息。
  • 退订频道和退订模式分别是订阅频道和订阅模式的反操作。

redis 订阅与发布的更多相关文章

  1. Redis订阅和发布模式和Redis事务

    -------------------Redis订阅和发布模式------------------- 1.概念     Redis 发布订阅(pub/sub)是一种消息通信模式:     发送者(pu ...

  2. redis订阅与发布系统

    一.概述 1.redis通过publish.subscribe等命令实现了订阅与发布模式. 2.这个功能提供两种信息机制,分别是订阅/发布到频道和订阅/发布到模式. 二.频道的订阅与信息发送 1.re ...

  3. Redis订阅与发布

    发布与订阅模型在许多编程语言中都有实现,也就是我们经常说的设计模式中的一种--观察者模式.在一些应用场合,例如发送方并不是以固定频率发送消息,如果接收方频繁去咨询发送方,这种操作无疑是很麻烦并且不友好 ...

  4. redis订阅与发布(把redis作为消息中间件)

    订阅频道127.0.0.1:6379> subscribe chat1Reading messages... (press Ctrl-C to quit)1) "subscribe&q ...

  5. PHP swoole实现redis订阅和发布

    前戏:实现用户下单,服务器通知后台接收订单...类似美团外卖 1.首先要实现一个订阅程序 $result = $client->connect('127.0.0.1', 6379, functi ...

  6. 上下文管理、线程池、redis订阅和发布

    一:上下文管理: 对于一些对象在使用之后,需要关闭操作的.比如说:socket.mysql数据库连接.文件句柄等. 都可以用上下文来管理. 语法结构: Typical usage: @contextm ...

  7. Redis 订阅发布 - Jedis实现

    Redis 订阅发布 - Jedis实现 我想到使用Redis的订阅发布模式是用来解决推送问题的-. 对于概念性的叙述,多多少少还是要提一下的: ​ 什么是Redis发布订阅?Redis发布订阅是一种 ...

  8. 15天玩转redis —— 第九篇 发布/订阅模式

    本系列已经过半了,这一篇我们来看看redis好玩的发布订阅模式,其实在很多的MQ产品中都存在这样的一个模式,我们常听到的一个例子 就是邮件订阅的场景,什么意思呢,也就是说100个人订阅了你的博客,如果 ...

  9. ServiceStack.Redis订阅发布服务的调用(Z)

      1.Redis订阅发布介绍Redis订阅发布是一种消息通信模式:发布者(publisher)发送消息,订阅者(Subscriber)接受消息.类似于设计模式中的观察者模式.发布者和订阅者之间使用频 ...

随机推荐

  1. HTTP协议入门

    1.概述 (1)HTTP是应用层协议,是从Web服务器传输超文本到本地浏览器的传送协议,端口号为80.(2)默认情况下HTTP使用TCP,但是也可以基于以后存在的其他可靠传输协议.由于UDP无法提供可 ...

  2. 动态读取文件持续显示在UI上

    private void DisplayLogInfo(FileInfo _LastFile) { if (_LastFile != null) { StreamReader sr = null; t ...

  3. Java中Bean是什么

    javaBean在MVC设计模型中是model,又称模型层,在一般的程序中,我们称它为数据层,就是用来设置数据的属性和一些行为,然后我会提供获取属性和设置属性的get/set方法JavaBean是一种 ...

  4. salesforce零基础学习(七十四)apex:actionRegion以及apex:actionSupport浅谈

    我们在开发中,很难会遇见不提交表单的情况.常用的apex:commandButton,apex:commandLink,apex:actionFunction,apex:actionSupport.他 ...

  5. sql求和isnull注意事项

    如果不用isnull函数判断则计算出来如果有一列是null 则相加就是null,如 两列:1 null 1+null = nullselect sum(ISNULL(jinE,0)+ISNULL(qi ...

  6. 修改phpstorm的字体样式和大小

    默认的字体实在太小,也太丑,必须修改下.就是强迫症,没错.下面截图配文字说明下 方法/步骤   首先进入设置,不解释   先设置软件界面上的字体.进入设置之后,选择(外观)Appearance.之后软 ...

  7. [命令行] curl查询公网出口IP

    转载:http://blog.csdn.net/orangleliu/article/details/51994513 不管是在家里还是办公室,或者是公司的主机,很多时候都是在内网中,也就是说很多都是 ...

  8. if和for的几个经典题目

    1.有一对幼兔,幼兔1个月后长成小兔,小兔1个月后长成成兔并生下一对幼兔,问几年后有多少对兔子,幼兔.小兔.成兔对数分别是多少. 幼兔 1 小兔 0 成兔 0幼兔 0 小兔 1 成兔 0 幼兔 1 小 ...

  9. JAVA基础——编程练习(二)

    JAVA编程练习(二) 今天我为了巩固之前的java基础知识的学习,再次进行实战演习,编写了一个小小的java控制台程序,主要是运用java面向对象的思想来完成这个小项目. 一.项目背景介绍 根据所学 ...

  10. SQL数据库操作(CURD)

    对数据仓库的操作(CURD): 新增:  create database db_test; 新增的时候设置编码: create database da_test_1 character set utf ...