Redis中的订阅发布(二)

订阅与发布

订阅频道

每当客户端执行SUBSCRIBE命令订阅某个或某些频道的时候,服务器都会将客户端与被订阅的频道
在pubsub_channels字典中进行关联。
根据频道是否已经有其他订阅者,关联操作分为两种情况执行:

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

例子

  • 举个例子。假设服务器pubsub_channels字典的当前状态如图所示,那么当客户端client-10086执行命令
SUBSCRIBE "news.sport" "news.movie"

之后,pubsub_channels字典将更新至如图所示的状态,其中用虚线包围的是新添加的节点:
1.更新后的pubsub_channels字典新增了"news.movie"键,该键对应的链表值只包含一个client-10086节点,表示目前只有client-10086一个客户端在订阅"news.movie"频道
2.至于原本就已经有客户端在订阅的"news.sport"频道,client-10086的节点放在了频道对应链表的末尾,排在client-4节点的后面
在这里插入图片描述
在这里插入图片描述

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
中解除客户端与被退订频道之间的关联:

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

例子

  • 举个例子,假设pubsub_channels的当前状态如图所示,那么当客户端client-10086执行命令:
UNSUBSCRIBE "news.sport" "news.movie"

之后,图中用虚线包围的两个节点将被删除如图所示
1.在pubsub_channels字典更新之后,client-10086的信息已经从"news.sport"频道和"news.movie"频道的订阅者链表中被删除了
2.另外,因为删除client-10086之后,频道"news.movie"已经没有任何订阅者,因此键"news.movie"也从字典中被删除了
在这里插入图片描述
在这里插入图片描述

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_channels属性里面,与此类似,服务器也将所有模式的订阅都保存在服务器状态的pubsub_patterns属性里面:

struct redisServer {
// ...// 保存所有模式订阅关系
list *pubsub_patterns;// ...
};

pubsub_patterns属性是一个链表,链表中的每个节点都包含着一个pubsubPatttern结构,这个结构的pattern属性记录了被订阅的模式,而client属性则记录了订阅模式的客户端:

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

例子

  • 举个例子。如图所示是一个pubsubPattern结构示例,它显示客户端client-9正在订阅模式"news.".
    图中展示了pubsub_patterns链表示例,这个链表记录了以下信息:
    1.客户端client-7正在订阅模式"music.
    "
    2.客户端client-8正在订阅模式"book."
    3.客户端client-9正在订阅模式"news.
    "
    在这里插入图片描述
    在这里插入图片描述

订阅模式

每当客户端执行PSUBSCIRBE命令订阅某个或某些模式的时候,服务器会对每个被订阅的模式执行以下两个操作:

  • 1.新键一个pubsubPattern结构,将结构的pattern属性设置为被订阅的模式,client属性设置为订阅模式的客户端
  • 2.将pubsubPattern结构添加到pubsub_patterns链表的表尾。
例子
  • 举个例子,假设服务器中的pubsub_pattern链表的当前状态如图所示。
    当客户端client-9执行命令:
PSUBSCRIBE "news.*"

之后,pubsub_patterns链表将更新至如图所示的状态,其中用虚线包围的是新添加的pubsubPattern结构

PSUBSCRIBE命令的实现原理

可以用以下伪代码来描述

def psubscribe(*all_input_patterns):
# 遍历输入的所有模式
for pattern in all_input_patterns:
# 创建新的pubsubPattern结构
# 记录被订阅的模式,以及订阅模式的客户端
pubsubPattern = create_new_pubsubPattern()
pubsubPattern.client = client
pubsubPattern.pattern = pattern# 将新的pubsubPattern追加到pubsub_patterns链表末尾
server.pubsub_patterns.append(pubsubPattern)

退订模式

模式的退订模式PUNSUBSCRIBE是PSUBSCRIBE命令的反操作:当一个客户端退订某个或某些模式的时候,服务器将在pubsub_patterns链表中查找并删除那些pattern属性为退订模式,并且client属性为执行退订命令的客户端的pubsubPattern结构

例子
  • 举个例子。假设服务器pubsub_patterns链表的当前状态如图所示,当客户端client-9执行命令:
PUNSUBSCRIBE "news.*"

之后,client属性为client-9,pattern属性为"news.*"的pubsubPattern结构将被删除,pubsub_patterns链表将更新至如图所示的样子
在这里插入图片描述
在这里插入图片描述

PUNSUBSCRIBE命令的实现原理

可以用以下伪代码来描述

def punsubscribe(*all_input_patterns):
# 遍历所有要退订的模式
for pattern in all_input_patterns:
# 遍历pubsub_patterns
for pubsubPattern in server.pubsub_patterns:
# 如果当前客户端和pubsubPattern记录的客户端相同
# 并且要退订的模式也和pubsubPattern记录的模式相同
if client == pubsubPattern.client and \ pattern == pubsubPattern.pattern:# 那么将这个pubsubPattern从链表删除
server.pubsub_patterns.remove(pubsubPattern)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/310734.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023年图灵奖揭晓,你怎么看?

阿维威格德森 (Avi Wigderson)是一位杰出的学者,他在理论计算机科学领域的贡献和研究成果备受认可。他对于理解计算中的随机性和伪随机性的作用所做出的开创性贡献将深远影响该领域的发展。这项荣誉是对他杰出成就的高度认可,也将激励更多人在理论计算机…

一文掌握 React 开发中的 JavaScript 基础知识

前端开发中JavaScript是基石。在 React 开发中掌握掌握基础的 JavaScript 方法将有助于编写出更加高效、可维护的 React 应用程序。 在 React 开发中使用 ES6 语法可以带来更简洁、可读性更强、功能更丰富,以及更好性能和社区支持等诸多好处。这有助于提高开发效率,并构建出更…

关于Wordpress的操作问题1:如何点击菜单跳转新窗口

1.如果打开,外观-菜单-菜单结构内,没有打开新窗口属性,如图: 2.在页面的最上部,点开【显示选项】,没有这一步,不会出现新跳转窗口属性 3.回到菜单结构部分,就出现了

php单文件实现文件批量预览——图片,音频,视频

有一天,无意中发现了一个在线文件预览地址。即那种暴露目录的地址。该目录下清一色的图片。觉得一个个点击进去查看太麻烦了,因此特意写了这个文件预览代码。单php文件,放到站点下运行即可。 1.实用场景 比如一个在线站点文件目录如下&#…

冯诺依曼结构理解

冯诺依曼结构 存储器:内存 数据是要在计算机的体系结构中进行流动的,在流动过程中对数据加工处理 从一个设备到另一个设备,本质是一种拷贝 CPU的计算速度是很快的,所以数据设备间的拷贝效率,决定了计算机整体的基本效率…

Excel 记录单 快速录入数据

一. 调出记录单 ⏹记录单功能默认是隐藏的,通过如下如图所示的方式,将记录单功能显示出来。 二. 录入数据 ⏹先在表格中录入一行数据,给记录单一个参考 ⏹将光标至于表格右上角,然后点击记录单按钮,调出记录单 然后点…

Go微服务: 服务熔断hystrix原理

微服务熔断概述 go 微服务保稳三剑客: 熔断,限流,负载均衡微服务熔断(hystrix-go) 与 服务雪崩效应 在服务里面,有服务A调用服务B, 会有依赖调用关系,同时服务C被B依赖如果依赖关系在生产环境中多的话,C挂了之后服务B原…

ins视频批量下载,instagram批量爬取视频信息

简介 Instagram 是目前最热门的社交媒体平台之一,拥有大量优质的视频内容。但是要逐一下载这些视频往往非常耗时。在这篇文章中,我们将介绍如何使用 Python 编写一个脚本,来实现 Instagram 视频的批量下载和信息爬取。 我们使用selenium获取目标用户的 HTML 源代码,并将其保存…

pyskl手势/动作识别的实现与pytorch cuda环境部署保姆教程

恭喜你,找到这篇不需要翻墙就能够成功部署的方法。在国内布置这个挺麻烦的,其他帖子会出现各种问题不能完全贯通。便宜你了。。 实话5年前我用1080训练过一个基于卷积和ltsm的手势识别,实话实说感觉比现在效果好。是因为现在的注意力都在tra…

贝叶斯网络

贝叶斯网络,又称为贝叶斯信念网络或贝叶斯网络模型,是一种概率图模型,由代表变量节点及连接这些节点的有向边构成。这种网络模型由Judea Pearl于1985年首次提出,用于表示和分析变量之间概率关系,从而进行不确定性推理。…

参会记录|全国多媒体取证暨第三届多媒体智能安全学术研讨会(MAS‘2024)

前言:2024年4月13日上午,我与实验室的诸位伙伴共聚江西南昌的玉泉岛大酒店,参加了为期一天半的全国多媒体取证暨第三届多媒体智能安全学术研讨会(MAS’2024)。本届学术研讨会由江西省计算机学会、江西省数字经济学会主…

自然语言处理: 第二十七章LLM训练超参数

前言: LLM微调的超参大致有如下内容,在本文中,我们针对这些参数进行解释 training_arguments TrainingArguments(output_dir"./results",per_device_train_batch_size4,per_device_eval_batch_size4,gradient_accumulation_steps2,optim"adamw_8bi…

【翻译】再见, Clean Code!

🌈个人主页: 鑫宝Code 🔥热门专栏: 闲话杂谈| 炫酷HTML | JavaScript基础 ​💫个人格言: "如无必要,勿增实体" 文章目录 【翻译】再见, Clean Code!正文那是一个深夜次日早晨这只是一个阶段 【翻译】再见…

面试八股——JVM★

类加载 类加载器的定义 类加载器的类别 类装载的执行过程 类的装载过程: 加载: 验证: 准备: 这里设置初始值并不是传统意义的设置初始值(那个过程在初始化阶段)。 解析: 初始化: …

微信小程序|自定义弹窗组件

目录 引言小程序的流行和重要性自定义弹出组件作为提升用户体验和界面交互的有效方式什么是自定义弹出组件自定义弹出组件的概念弹出层组件在小程序中的作用和优势为什么需要自定义弹出组件现有的标准弹窗组件的局限性自定义弹出组件在解决这些问题上的优势

基于Springboot的校园闲置物品交易网站

基于SpringbootVue的校园闲置物品交易网站的设计与实现 开发语言:Java数据库:MySQL技术:SpringbootMybatis工具:IDEA、Maven、Navicat 系统展示 用户登录 首页 商品信息展示 商品资讯 后台管理 后台首页 用户管理 商品类型管…

《系统架构设计师教程(第2版)》第9章-软件可靠性基础知识-04-软件可靠性设计

文章目录 1. 容错设计技术1.1 恢复块设计1.2 N版本程序设计1.3 冗余设计 2. 检错技术3. 降低复杂度设计4. 系统配置中的容错技术4.1 双机热备技术4.1.1 双机热备模式4.1.2 双机互备模式4.1.3 双机双工 4.2 服务器集群技术 1. 容错设计技术 1.1 恢复块设计 恢复块设计 选择一组…

用于 SQLite 的异步 I/O 模块(二十四)

返回:SQLite—系列文章目录 上一篇:SQLite的PRAGMA 声明(二十三) 下一篇:SQLite、MySQL 和 PostgreSQL 数据库速度比较(本文阐述时间很早比较,不具有最新参考性)(二…

亚马逊、沃尔玛自养号测评技术解析:如何降低潜在风险

亚马逊等电商平台在全球范围内迅速扩张,竞争愈发激烈。为提升产品排名和销量,众多卖家选择采用自养号测评的策略。然而,自养号测评技术并非完美无缺,它存在着一定的技术局限性。由于缺乏对自养号原理及底层环境搭建的深入理解&…

华为配置通过流策略实现流量统计

配置通过流策略实现流量统计示例 组网图形 图1 配置流策略实现流量统计组网图 设备 接口 接口所属VLAN 对应的三层接口 IP地址 SwitchA GigabitEthernet1/0/1 VLAN 10 - - GigabitEthernet1/0/2 VLAN 20 - - GigabitEthernet1/0/3 VLAN 10、VLAN 20 - - S…