redis发布订阅模型

news2024/11/14 3:54:07

文章目录

    • 发布与订阅
      • 1.频道订阅和退订
        • 1.1订阅频道`subscribe`
          • **伪代码**
        • 1.2 退订频道
          • 伪代码
      • 2.模式订阅和退订
        • 2.1订阅模式`psubscribe`
        • 2.2 退订模式
      • 3.发送消息
        • 3.1 消息发送频道订阅者
          • 伪代码
        • 3.2消息发送模式订阅者
          • 伪代码
      • 总结的Publish
      • 4.查看订阅消息
        • 4.1 `pubsub channels`
        • 4.2 `pubsub numsub`
          • 伪代码
        • 4.3 `pubsub numpat`
          • 伪代码
      • 5.回顾

发布与订阅

Redis的发布订阅基于publish,subscribe,psubscribe

订阅

subscribe "news.it"

发布

publish "news.it" "hello"

订阅

image-20230728101944396

发布

image-20230728102011059

订阅的状态的推进

image-20230728102744213

new.it发送消息

image-20230728102755236

1.频道订阅和退订

Redis订阅关系保存在服务器状态的pubsub_channels字典

keychannel, value为链表,链表上有订阅该频道的Client

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

如图所示

image-20230728141631387

1.1订阅频道subscribe

Client订阅pubsub_channels有两种情况

  • 频道有其他订阅者,把value添加到链表尾部
  • 没有订阅者,就把先创建key再添加value
subscribe "news.sport" "news.movie"

image-20230728144804639

伪代码
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) = (1
		# 将订阅者添加到频道所对应的链表的未尾
		server.pubsub channels [channel].append (client)

1.2 退订频道

unsubscribe "news.sport"  "news.movie"

image-20230728145128522

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

2.模式订阅和退订

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

pubsub_patterns是链表,每个节点都包括一个pubsub_Patterns结构

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

示意图

image-20230728153722027

client-7,8,9分别在订阅 music.*,book.*,news.*

image-20230728154159308

2.1订阅模式psubscribe

客户端执行psubscribe,服务端会执行两个操作

  1. 新建pubsubPattern,讲结构的pattern设置为被订阅的模式
  2. pubsubPattern添加到pubsub_patterns链表尾部

执行psubscribe之前的pubsub_patterns

image-20230728155257011

执行psubscribe之后的pubsub_patterns

def subscribe (*all_ input patterns):
 #遍历输入的所有模式
	for pattern in all input patterns:
		#创建新的 pubsubPattern 结构
   # 记录被订间的模式,以及订阅模式的容户端
   pubsubPattern = create new pubsubPattern (
   pubsubPattern.client= client
   pubsubPattern.pattern= pattern
   # 将新的 pubsubPattern 追加到pubsubpatterns链表末尾
   server.pubsub patterns.append (pubsubPattern)

2.2 退订模式

punsubscribe

image-20230728160920126

当执行退订模式的时候,相应的pubsubPattern结构会被删除

执行punsubscribe "news.*"之前的pubsub_patterns

image-20230728161636374

执行punsubscribe "news.*"之后的pubsub_patterns

image-20230728161700300

def unsubscribe (*all input patterns) :
		# 遍历所有要退订的模式
		for pattern in all input patterns:
				# 遍历 pubsub patterns 链表中的所有pubsubPattern 结构
				for pubsubPattern in server.pubsub patterns:
							#如果当前客户端和pubsuibPattern 记录的客户端相同
							#并且要退订的模式也和 pubsubPattern 记录的模式相同
							if client == pubsubPattern.client and \
								pattern == pubsubPattern.pattern:
                # 那么将这个pubsubPattern 从链表中利除
                server.pubsub patterns.remove (pubsubPattern)

3.发送消息

PUBLISH <channel> <message>

message发送到channel的订阅者

一个或多个pattern与频道channel匹配

3.1 消息发送频道订阅者

image-20230728162209425

PUBLISH "news.it" "hello"		// client-1,client-2,client-3都会收到
伪代码
def channel_publish (channel, message) :
# 如果 channel键不存在于pubsub channels 字典中
# 那么说明 channe1 频道没有任何订阋者
# 程序不做发送动作,直接返回
if channel not in server.pubsub channels:
	return
    
# 运行到这里,说明 channel 频道至少有一个订阅者
# 程序遍历 channe1 频道的订阅者链表
# 将消,息发送给所有订阅者
for subscriber in server.pubsub channels [channel] :
	send message (subscriber, message)

3.2消息发送模式订阅者

image-20230728162832130

PUBLISH "news.it" "hello"		// 和news.*匹配,news.*会收到
伪代码
def pattern_publish (channel, message):
	# 遍历所有模式订阅消息
	for pubsubPattern in server.pubsub patterns:
		# 如果频道和模式相匹配
		if match (channel, pubsubPattern.pattern):
			#那么格消息发洪给订回该模式的容户瑞
			send message (pubsubPattern.client, message)

总结的Publish

def publish (channel, message):
		# 将消息发送给 channe1 频道的所有订间者
		channel publish (channel, message)
				#将消息发送给所有和 channel 頻道相匹配的模式的订回者
				pattern publish (channel, message)

4.查看订阅消息

PUBSUB查看频道或者模式相关消息

4.1 pubsub channels

pubsub channels <pattern>(可选)  //pattern可选,选择表示返回匹配的频道
def pubsub channels (pattern=None) :
	#一个列表,用于记录所有符合条件的频道
	channel_list = []
    
	# 遍历服务器中的所有频道
	#(也即是pubsub channels 字典的所有键)
	for channel in server.pubsub channels:
		# 当以下两个条件的任意一个满足时,将频道添加到链表里面:
		#1 )用户没有指定pattezn 参数
		#2 )用户指定了pattern 参数,并且channel 和pattern 匹配
		if (pattern is None) or match (channel, pattern):
		channel list.append (channel)
# 向客户端返回频道列表
return channel_list      

image-20230728164616065

被订阅的4个频道

redis> PUBSUB CHANNELS
1)"news. it"
2)"news.sport"
3)"news. business"
4)"news.movie"

进行频道pattern筛选

redis> PUBSUB CHANNELS "news. [is]*"	
  //返回所有名称以"news."开头,并且后面紧跟着一个或多个字母"i"或"s"的频道的列表
1)"news.it"
2)"news. sport"

4.2 pubsub numsub

pubsub numsub [channel-1 channel-2 ...channel-n]  //接受多个频道作为入参,返回这些频道的订阅者
伪代码
def pubsub numsub (*all input channels) :
	# 遍历输入的所有频道
	for channel in all input channels:
		#如果 pubsub channels 宇典中没有 channe1 这个键
		#那么说明 channel 频道没有任何订回者
		if channel not in server.pubsub channels:
			#返回频道名
      reply channel name (channel)
      # 订阅者数量为。
      reply subscribe count (0)
#如果 pubsub channels 字典中存在 channe1 键
# 那么说明channel 频道至少有一个订阅者
else:
      #返回频道名
      reply channel name (channel)
      # 订阅者链表的长度就是订用者数量
      reply subscribe count (len (server .pubsub_channels [channel]))

image-20230728170459519

redis> PUBSUB NUMSUB news.it news.sport news.business news.movie
1)"news. it"
2)"3"
3)"news. sport"
4)"2"
5)"news.business"
6)"2"
7)"news. movie"
8)"1"

4.3 pubsub numpat

返回服务器当前被订阅模式的数量

伪代码
def pubsub_numpat():
		# pubsub_patterns 链表长度是被订阅数量
reply pattern count (len(server.pubsub patterns))

image-20230728170821668

对于上方链表来说,执行pubsub numpat结果

redis> pubsub numpat
(integer) 3

5.回顾

  1. 服务器在pubsub_channels保存频道订阅关系,subscribeunsubscribe
  2. 服务器在pubsub_patterns保存模式订阅关系,psubscribepunsubscribe
  3. publish发送消息
  4. pubsub读取pubsub_channelspubsub_patterns来实现

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从前序与中序遍历序列构造二叉树,从中序与后序遍历序列构造二叉树

目录 从前序与中序遍历序列构造二叉树从中序与后序遍历序列构造二叉树 从前序与中序遍历序列构造二叉树 题目链接 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返…

深度学习Redis(2):持久化

前言 在上一篇文章中&#xff0c;介绍Redis的内存模型&#xff0c;从这篇文章开始&#xff0c;将依次介绍Redis高可用相关的知识——持久化、复制(及读写分离)、哨兵、以及集群。 本文将先说明上述几种技术分别解决了Redis高可用的什么问题&#xff1b;然后详细介绍Redis的持…

8.3 作业 c高级

1.递归实现&#xff0c;输入一个数&#xff0c;输出这个数的每一位&#xff1a; #include<myhead.h>void print_digit(int num) {if(num<10){printf("%d",num);puts("");}else{print_digit(num/10); //递归打印除最后一位外的数printf("%…

10.物联网操作系统之低功耗管理

一。低功耗管理概念及其应用 1.STM32低功耗设计详解 STM32的电源管理系统主要分为&#xff1a; 备份域 调压器供电电路 ADC电源电路 2.低功耗模式 1.运行模式 2.睡眠模式 3.停机模式 4.待机模式 &#xff08;1&#xff09;睡眠模式 在睡眠模式中&#xff0c;仅关闭了内核时钟&…

【计算机网络】网络层协议 -- ICMP协议

文章目录 1. ICMP协议简介2. ICMP协议格式3. ping命令4. ping命令与端口号没有关系&#xff01;&#xff01;&#xff01;5. traceroute命令 1. ICMP协议简介 ICMP&#xff08;Internet Control Message Protocol&#xff0c;控制报文协议&#xff09;&#xff0c;用于在IP主机…

22.Netty源码之解码器

highlight: arduino-light 抽象解码类 https://mp.weixin.qq.com/s/526p5f9fgtZu7yYq5j7LiQ 解码器 Netty 常用解码器类型&#xff1a; ByteToMessageDecoder/ReplayingDecoder 将字节流解码为消息对象&#xff1b;MessageToMessageDecoder 将一种消息类型解码为另外一种消息类…

关于时间的基本概念

年的标准——纪元 Era Epoch 在中国古代&#xff0c; 皇帝会订立年号来纪年&#xff0c; 比如贞观就是唐太宗订立的年号&#xff0c; 于是天下使用贞观元年&#xff0c;贞观二年的方式来纪年。皇帝可以因为各种原因更换年号&#xff0c;比如武则天在位21年&#xff0c; 使用了…

【vue】 el-table解决分页不能筛选全部数据的问题

前言 最近开发前端项目表格的时候&#xff0c;使用的是el-table&#xff0c;用到了对应的筛选功能&#xff0c;如下图所示 但发现实际只能筛选当前页&#xff0c;通过百度查找相关文章&#xff0c;发现原因是把筛选条件定义在列上&#xff0c;解决方法&#xff1a;所以我们把f…

HadoopWEB页面上传文件报错Couldn‘t upload the file course_info.txt

HadoopWEB页面上传文件报错Couldn’t upload the file course_info.txt 右键F2检查发现&#xff1a;文件上传PUT操作的IP地址是节点IP别名识别不到导致 解决方法&#xff1a;在WEB页面访问浏览器所在机器上面配置hosts映射地址(注意:配置的是浏览器访问的地址不是hadoop节点所在…

【项目 进程12】2.25 sigprocmask函数使用 2.26sigaction信号捕捉函数 2.27SIGCHILD信号

文章目录 2.25 sigprocmask函数使用2.26 sigaction信号捕捉函数内核实现信号捕捉的过程信号捕捉特性 2.27SIGCHILD信号 2.25 sigprocmask函数使用 阻塞信号集有时称作信号掩码。 联想&#xff1a;fcntl函数可以修改fd属性。 ./sigprocmask & //将程序设置为后台运行&…

JWT应用功能

JWT 一、 JWT 实现无状态 Web 服务 1、什么是有状态 有状态服务&#xff0c;即服务端需要记录每次会话的客户端信息&#xff0c;从而识别客户端身份&#xff0c;根据用户身份进行请求的处理&#xff0c;典型的设计如tomcat中的session。 例如登录&#xff1a;用户登录后&am…

SpringCloud《Eureka、Ribbon、Feign、Hystrix、Zuul》作用简单介绍

概述 SpringCloud是一个全家桶&#xff0c;包含多个组件。 本文主要介绍几个重要组件&#xff0c;也就是Eureka、Ribbon、Feign、Hystrix、Zuul这几个组件。 一、业务场景介绍 业务流程&#xff0c;支付订单功能 订单服务改变为已支付订单服务调用库存服务&#xff0c;扣减…

Webpack开启本地服务器;HMR热模块替换;devServer配置;开发与生成环境的区分与配置

目录 1_开启本地服务器1.1_开启本地服务器原因1.2_webpack-dev-server 2_HMR热模块替换2.1_认识2.2_开启HMR2.3_框架的HMR 3_devServer配置3.1_host配置3.2_port、open、compress 4_开发与生成环境4.1_如何区分开发环境4.2_入口文件解析4.3_区分开发和生成环境配置 1_开启本地服…

743. 网络延迟时间

有 n 个网络节点&#xff0c;标记为 1 到 n。 给你一个列表 times&#xff0c;表示信号经过 有向 边的传递时间。 times[i] (ui, vi, wi)&#xff0c;其中 ui 是源节点&#xff0c;vi 是目标节点&#xff0c; wi 是一个信号从源节点传递到目标节点的时间。 现在&#xff0c;…

iMX6ULL驱动开发 | OLED显示屏SPI驱动实现(SH1106,ssd1306)

周日业余时间太无聊&#xff0c;又不喜欢玩游戏&#xff0c;大家的兴趣爱好都是啥&#xff1f;我觉得敲代码也是一种兴趣爱好。正巧手边有一块儿0.96寸的OLED显示屏&#xff0c;一直在吃灰&#xff0c;何不把玩一把&#xff1f;于是说干就干&#xff0c;最后在我的imax6ul的lin…

泛微最近的漏洞利用工具

WeaverExploit_All 0x01 介绍 泛微最近的漏洞利用工具&#xff08;PS&#xff1a;2023&#xff09; 集成了QVD-2023-5012、CVE-2023-2523、CVE-2023-2648、getloginid_ofsLogin 漏洞利用 新增&#xff1a;WorkflowServiceXml 内存马注入、uploaderOperate文件上传漏洞、Del…

go-zero超强工具goctl的常用命令api,rpc,model及其构建的服务解析

goctl api 详情移步&#xff1a; go-zero的路由机制解析 基于go-zero的api服务刨析并对比与gin的区别 goctl rpc goctl支持多种rpc&#xff0c;较为流行的是google开源的grpc&#xff0c;这里主要介绍goctl rpc protoc的代码生成与使用。 protoc是grpc的命令&#xff0c;作用…

SpringBoot的pom文件、容器、组件

一、pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4…

springboot-mybatis的增删改查

目录 一、准备工作 二、常用配置 三、尝试 四、增删改查 1、增加 2、删除 3、修改 4、查询 五、XML的映射方法 一、准备工作 实施前的准备工作&#xff1a; 准备数据库表 创建一个新的springboot工程&#xff0c;选择引入对应的起步依赖&#xff08;mybatis、mysql驱动…

基于springboot的课程作业管理系统【附开题|ppt|万字文档(LW)和搭建文档】

主要功能 学生登录&#xff1a; ①首页、个人中心&#xff1a;修改密码、个人信息管理等 ②公告信息管理、课程信息管理、学生选课管理、作业布置管理、作业提交管理、作业评分管理、课程评价管理、课程资源管理 教师登录&#xff1a; ①首页、个人中心&#xff1a;修改密码、…