频道的订阅和退订

当一个客户端执行 SUBSCRIBE 命令, 订阅某个或某些频道的时候, 这个客户端与被订阅频道之间就建立起了一种订阅关系。

Redis 将所有频道的订阅关系都保存在服务器状态的 pubsub_channels 字典里面, 这个字典的键是某个被订阅的频道, 而键的值则是一个链表, 链表里面记录了所有订阅这个频道的客户端:

struct redisServer {// ...// 保存所有频道的订阅关系dict *pubsub_channels;// ...};

每当客户端执行 SUBSCRIBE 命令, 订阅某个或某些频道的时候, 服务器都会将客户端与被订阅的频道在 pubsub_channels 字典中进行关联。

根据频道是否已经有其他订阅者, 关联操作分为两种情况执行:

  • 如果频道已经有其他订阅者, 那么它在 pubsub_channels 字典中必然有相应的订阅者链表, 程序唯一要做的就是将客户端添加到订阅者链表的末尾。
  • 如果频道还未有任何订阅者, 那么它必然不存在于 pubsub_channels 字典, 程序首先要在 pubsub_channels 字典中为频道创建一个键, 并将这个键的值设置为空链表, 然后再将客户端添加到链表, 成为链表的第一个元素。

SUBSCRIBE 命令的实现可以用以下伪代码来描述:

def subscribe(*all_input_channels):# 遍历输入的所有频道for channel in all_input_channels:# 如果 channel 不存在于 pubsub_channels 字典(没有任何订阅者)# 那么在字典中添加 channel 键,并设置它的值为空链表if channel not in server.pubsub_channels:server.pubsub_channels[channel] = []# 将订阅者添加到频道所对应的链表的末尾server.pubsub_channels[channel].append(client)

UNSUBSCRIBE 命令的行为和 SUBSCRIBE 命令的行为正好相反 —— 当一个客户端退订某个或某些频道的时候, 服务器将从 pubsub_channels 中解除客户端与被退订频道之间的关联:

  • 程序会根据被退订频道的名字, 在 pubsub_channels 字典中找到频道对应的订阅者链表, 然后从订阅者链表中删除退订客户端的信息。
  • 如果删除退订客户端之后, 频道的订阅者链表变成了空链表, 那么说明这个频道已经没有任何订阅者了, 程序将从 pubsub_channels 字典中删除频道对应的键。

UNSUBSCRIBE 命令的实现可以用以下伪代码来描述:

def unsubscribe(*all_input_channels):# 遍历要退订的所有频道for channel in all_input_channels:# 在订阅者链表中删除退订的客户端server.pubsub_channels[channel].remove(client)# 如果频道已经没有任何订阅者了(订阅者链表为空)# 那么将频道从字典中删除if len(server.pubsub_channels[channel]) == 0:server.pubsub_channels.remove(channel)

模式的订阅和退订

前面说过,服务器将所有频道的订阅关系保存起来,与此类似,服务器也将所有模式的订阅关系存在了pubsub_Patterns属性里。

struct redisServer {// ...// 保存所有频道的订阅关系list *pubsub_patterns;// ...};

pubsub_Patterns属性是一个链表,每个结点是被订阅的模式,节点内记录了模式,节点内的client属性记录了订阅模式的客户端。

typedef struct pubsubPattern{//订阅模式的客户端redisClient *client;//被订阅的模式robj *pattern;
}pubsubPattern;

每当客户端执行PSUBSCRIBE这个命令来订阅某个或某些模式时,服务器会对每个被订阅的模式执行下面的操作:

1)新建一个pubsubPattern结构,设置好两个属性

2)将新节点加到pubsub_patterns尾部

伪代码实现:

def osubscribe(*all_input_patterns):#遍历所有输入的模式#记录被订阅的模式和对应的客户端pubsubPattern=create()pubsubPattern.client=clientpubsubPattern.pattern=pattern#插入链表末尾server.pub_patterns.append(pubsubPattern)

模式退订命令PUNSUBSCRIBE是PSUBSCRIBE的反操作

服务器将找到并删除那些被退订的模式

伪代码如下:(我想吐槽一下这样时间复杂度。。。没有更好的办法吗?)

def osubscribe(*all_input_patterns):#遍历所有退订的模式for pattern in all_input_patterns:#遍历每一个节点for pubsubPattern in server.pubsub_patterns:#如果客户端和模式都相同if client==pubsubPattern.client:if pattern==pubsubPattern.pattern:#删除server.pub_patterns.remove(pubsubPattern)

发送消息

当一个客户端执行PUBLISH<channel> <message>命令将消息发送给频道时,服务器需要:

1)把消息发送给所有本频道的订阅者

具体做法就是去pubsub_channels字典找到本频道的链表,也就是订阅名单,然后发消息

2)将消息发给,包含本频道的所有模式中的所有订阅者

具体做法就是去pubsub_patterns查找包含本频道的模式,并且把消息发送给订阅它们的客户端。

查看订阅信息

redis2.8新增三个命令,用来查看频道和模式的相关信息。

PUBLISH CHANNELS[pattern]用于返回服务器当前被订阅的频道,pattern可写可不写,不写就查看所有,否则查看与pattern匹配的对应频道

这个子命令是通过遍历pubsub_channels字典实现的。

PUBLISH NUMSUB[CHANNEL-1 CHANNEL-2.....]返回这些频道的订阅者数量

这个子命令是通过遍历pubsub_channels字典,查看对应链表长度实现的。

PUBLISH NUMPAT返回被订阅模式数量

这个子命令是通过返回pubsub_patterns的长度实现的。

总而言之,PUBSUB 命令的三个子命令都是通过读取 pubsub_channels 字典和 pubsub_patterns 链表中的信息来实现的。

redis——发布和订阅相关推荐

  1. Redis发布与订阅(pub/sub)

    Redis发布与订阅(pub/sub) 本文档翻译自: http://redis.io/topics/pubsub . SUBSCRIBE . UNSUBSCRIBE 和 PUBLISH 三个命令实现 ...

  2. 6. Redis 发布与订阅

    文章目录 6. Redis 发布与订阅 为什么需要发布.订阅 发布/订阅如何使用? :one:基于频道发布 SUBSCRIBE:频道订阅 PUBLISH:向频道发送消息 UNSUBSCRIBE:退订频 ...

  3. Redis发布和订阅

    一.什么是Redis发布和订阅 Redis的发布(pub)和订阅(sub)是一种消息通信模式.它包含有三个角色分别是:发送者.订阅者.频道. Redis客户端可以订阅多个任意的频道. Redis发布和 ...

  4. Redis 发布和订阅

    Redis 发布和订阅 什么是发布和订阅 Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息. Redis 客户端可以订阅任意数量 ...

  5. redis发布与订阅消息

    2019独角兽企业重金招聘Python工程师标准>>> Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. Redis 客 ...

  6. Redis发布与订阅——PUBLISH SUBSCRIBE

    2019独角兽企业重金招聘Python工程师标准>>> Redis发布与订阅--PUBLISH  & SUBSCRIBE 一般来说,发布与订阅(又称pub/sub)的特点是 ...

  7. redis发布与订阅

    Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. Redis 客户端可以订阅任意数量的频道. 以下实例演示了发布订阅是如何工作的.在我们实 ...

  8. redis 发布和订阅 持久化 事务 缓存问题

    redis的发布订阅 使用数据类型lists 原理 可以有多个消费者和订阅者 订阅者:subscribe cla 命令 执行成功后 subscribe :表示成功订阅到响应 第二个元素:提供的频道 第 ...

  9. redis 发布与订阅

    一.简介 Redis提供了发布订阅功能,可以用于消息的传输 Redis的发布订阅机制包括三个部分,publisher,subscriber和Channel 发布者和订阅者都是Redis客户端,Chan ...

  10. Redis发布与订阅模式

    Redis的Pub/Sub实现了发布/订阅消息范式,发布者将消息发布到不同的频道,订阅者订阅感兴趣的频道消息,而不需要关心是谁在发布.这种发布者和订阅者的解耦合方式可以极大的扩展的扩展性网络拓扑. 为 ...

最新文章

  1. java response返回xml_Spring 返回Xml格式
  2. linux 视频相关资源
  3. 图像识别最新赛事!总奖金31万,一起组队吗?
  4. opengl 区域填充之种子填充线扫描法
  5. 智能会议系统(17)--- Linphone用户注册
  6. 金山云肖江:5G推动智慧人居产业到达新高度
  7. 数学建模优化模型简单例题_数学建模案例分析--最优化方法建模7习题六
  8. AdventureWorks2012.mdf的使用
  9. [技术交流]一些技术网站推荐。金融IT。
  10. 仿微信朋友圈图片点击放大效果
  11. Unity制作圆环进度条加载场景资源
  12. 语句的认识,选择语句和循环语句(2022.11.13)
  13. QCC305X-QCC304x系列开发教程(系统篇)之3.4-Mirroring详解
  14. ARM服务器和云手游
  15. PHP面向对象基础七
  16. CentOS 6.5挂载windows NTFS硬盘
  17. 目标检测YOLO系列------YOLO简介
  18. Python基础经典问题-求sin正弦值
  19. java如何连接rfid_Java + Uno + RFID:java中的调用方法读取rfid
  20. 如何让XP系统拥有纯DOS

热门文章

  1. ubuntu 14.04 ssh
  2. I2C设备驱动编写,struct i2c_device_id,struct i2c_driver,i2c_add_driver,i2c_register_board_info
  3. 【转】【C#】使用fo-dicom完成BMP,JPG,PNG图片转换为DICOM文件
  4. 【转】VS工具:实时可视化树
  5. 【转】WOPI host消息体结构
  6. Python 数据分析三剑客之 Pandas(五):统计计算与统计描述
  7. CCIE理论-第九篇-IPV6详细介绍
  8. 【HDU - 5878】I Count Two Three(打表)
  9. 【POJ - 2253】Frogger(floyd,或 部分瓶颈生成树的最大边)
  10. 【牛客 - 317B】小a与204(贪心,构造,水题)