当前位置: 首页 > news >正文

Redis消息传递:发布订阅模式详解

目录

1.Redis发布订阅简介

2.发布/订阅使用

   2.1 基于频道(Channel)的发布/订阅

   2.2 基于模式(pattern)的发布/订阅

3.深入理解Redis的订阅发布机制

   3.1 基于频道(Channel)的发布/订阅如何实现的?

   3.2 基于模式(Pattern)的发布/订阅如何实现的?

   3.3 SpringBoot结合Redis发布/订阅实例?


1.Redis发布订阅简介

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。

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

作为例子, 下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

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

 

2.发布/订阅使用

Redis有两种发布/订阅模式:

  • 基于频道(Channel)的发布/订阅
  • 基于模式(pattern)的发布/订阅

   2.1 基于频道(Channel)的发布/订阅

"发布/订阅"模式包含两种角色,分别是发布者和订阅者。发布者可以向指定的频道(channel)发送消息; 订阅者可以订阅一个或者多个频道(channel),所有订阅此频道的订阅者都会收到此消息。

  • 发布者发布消息

发布者发布消息的命令是 publish,用法是 publish channel message,例如向 channel1.1说一声hi

 

这样消息就发出去了。返回值表示接收这条消息的订阅者数量。发出去的消息不会被持久化,也就是有客户端订阅channel:1后只能接收到后续发布到该频道的消息,之前的就接收不到了。

  • 订阅者订阅频道

订阅频道的命令是 subscribe,可以同时订阅多个频道,用法是 subscribe channel1 [channel2 ...],例如新开一个客户端订阅上面频道:(不会收到消息,因为不会收到订阅之前就发布到该频道的消息)

执行上面命令客户端会进入订阅状态,处于此状态下客户端不能使用除subscribeunsubscribepsubscribepunsubscribe这四个属于"发布/订阅"之外的命令,否则会报错。

进入订阅状态后客户端可能收到3种类型的回复。每种类型的回复都包含3个值,第一个值是消息的类型,根据消类型的不同,第二个和第三个参数的含义可能不同。

消息类型的取值可能是以下3个:

  • subscribe。表示订阅成功的反馈信息。第二个值是订阅成功的频道名称,第三个是当前客户端订阅的频道数量。
  • message。表示接收到的消息,第二个值表示产生消息的频道名称,第三个值是消息的内容。
  • unsubscribe。表示成功取消订阅某个频道。第二个值是对应的频道名称,第三个值是当前客户端订阅的频道数量,当此值为0时客户端会退出订阅状态,之后就可以执行其他非"发布/订阅"模式的命令了。

   2.2 基于模式(pattern)的发布/订阅

如果有某个/某些模式和这个频道匹配的话,那么所有订阅这个/这些频道的客户端也同样会收到信息。

  • 用图例解释什么是基于模式的发布订阅

下图展示了一个带有频道和模式的例子, 其中 tweet.shop.* 模式匹配了 tweet.shop.kindle 频道和 tweet.shop.ipad 频道, 并且有不同的客户端分别订阅它们三个:

当有信息发送到 tweet.shop.kindle 频道时, 信息除了发送给 clientX 和 clientY 之外, 还会发送给订阅 tweet.shop.* 模式的 client123 和 client256 :

另一方面, 如果接收到信息的是频道 tweet.shop.ipad , 那么 client123 和 client256 同样会收到信息:

 

  • 基于模式的例子

通配符中?表示1个占位符,*表示任意个占位符(包括0),?*表示1个以上占位符。

publish发布

psubscribe订阅 

  • 注意点

(1)使用psubscribe命令可以重复订阅同一个频道,如客户端执行了psubscribe c? c?*。这时向c1发布消息客户端会接受到两条消息,而同时publish命令的返回值是2而不是1。同样的,如果有另一个客户端执行了subscribe c1psubscribe c?*的话,向c1发送一条消息该客户顿也会受到两条消息(但是是两种类型:message和pmessage),同时publish命令也返回2.

(2)punsubscribe命令可以退订指定的规则,用法是: punsubscribe [pattern [pattern ...]],如果没有参数则会退订所有规则。

(3)使用punsubscribe只能退订通过psubscribe命令订阅的规则,不会影响直接通过subscribe命令订阅的频道;同样unsubscribe命令也不会影响通过psubscribe命令订阅的规则。另外需要注意punsubscribe命令退订某个规则时不会将其中的通配符展开,而是进行严格的字符串匹配,所以punsubscribe * 无法退订c*规则,而是必须使用punsubscribe c*才可以退订。(它们是相互独立的,后文可以看到数据结构上看也是两种实现)

3.深入理解Redis的订阅发布机制

   3.1 基于频道(Channel)的发布/订阅如何实现的?

底层是通过字典(图中的pubsub_channels)实现的,这个字典就用于保存订阅频道的信息:字典的键为正在被订阅的频道, 而字典的值则是一个链表, 链表中保存了所有订阅这个频道的客户端。

  • 数据结构

比如说,在下图展示的这个 pubsub_channels 示例中, client2 、 client5 和 client1 就订阅了 channel1 , 而其他频道也分别被别的客户端所订阅:

  • 订阅

当客户端调用 SUBSCRIBE 命令时, 程序就将客户端和要订阅的频道在 pubsub_channels 字典中关联起来。

举个例子,如果客户端 client10086 执行命令 SUBSCRIBE channel1 channel2 channel3 ,那么前面展示的 pubsub_channels 将变成下面这个样子:

  • 发布

当调用 PUBLISH channel message 命令, 程序首先根据 channel 定位到字典的键, 然后将信息发送给字典值链表中的所有客户端。

比如说,对于以下这个 pubsub_channels 实例, 如果某个客户端执行命令 PUBLISH channel1 "hello moto" ,那么 client2 、 client5 和 client1 三个客户端都将接收到 "hello moto" 信息:

  • 退订

使用 UNSUBSCRIBE 命令可以退订指定的频道, 这个命令执行的是订阅的反操作: 它从 pubsub_channels 字典的给定频道(键)中, 删除关于当前客户端的信息, 这样被退订频道的信息就不会再发送给这个客户端。

   3.2 基于模式(Pattern)的发布/订阅如何实现的?

底层是pubsubPattern节点的链表。

  • 数据结构 redisServer.pubsub_patterns 属性是一个链表,链表中保存着所有和模式相关的信息:

链表中的每个节点都包含一个 redis.h/pubsubPattern 结构:

 

client 属性保存着订阅模式的客户端,而 pattern 属性则保存着被订阅的模式。

每当调用 PSUBSCRIBE 命令订阅一个模式时, 程序就创建一个包含客户端信息和被订阅模式的 pubsubPattern 结构, 并将该结构添加到 redisServer.pubsub_patterns 链表中。

作为例子,下图展示了一个包含两个模式的 pubsub_patterns 链表, 其中 client123 和 client256 都正在订阅 tweet.shop.* 模式:

  • 订阅

如果这时客户端 client10086 执行 PSUBSCRIBE broadcast.list.* , 那么 pubsub_patterns 链表将被更新成这样

通过遍历整个 pubsub_patterns 链表,程序可以检查所有正在被订阅的模式,以及订阅这些模式的客户端。

  • 发布

发送信息到模式的工作也是由 PUBLISH 命令进行的, 显然就是匹配模式获得Channels,然后再把消息发给客户端。

  • 退订

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

   3.3 SpringBoot结合Redis发布/订阅实例?

最佳实践是通过RedisTemplate,关键代码如下:

// 发布
redisTemplate.convertAndSend("my_topic_name", "message_content");// 配置订阅
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
container.addMessageListener(xxxMessageListenerAdapter, "my_topic_name");

本篇文章借鉴于:订阅与发布 — Redis 设计与实现 (redisbook.readthedocs.io) 

相关文章:

Redis消息传递:发布订阅模式详解

目录 1.Redis发布订阅简介 2.发布/订阅使用 2.1 基于频道(Channel)的发布/订阅 2.2 基于模式(pattern)的发布/订阅 3.深入理解Redis的订阅发布机制 3.1 基于频道(Channel)的发布/订阅如何实现的? 3.2 基于模式(Pattern)的发布/订阅如何实现的? 3.3 Sp…...

最强自动化测试框架Playwright(36)- 句柄

剧作家可以为页面 DOM 元素或页面内的任何其他对象创建句柄。这些句柄存在于 Playwright 进程中,而实际对象位于浏览器中。有两种类型的句柄: JSHandle 引用页面中的任何 JavaScript 对象ElementHandle 引用页面中的 DOM 元素,它具有额外的方…...

推荐一个绘图平台(可替代Visio)

不废话,简易记网址: draw.io 网站会重定向到:https://app.diagrams.net/...

【探索Linux】—— 强大的命令行工具 P.6(调试器-gdb、项目自动化构建工具-make/Makefile)

阅读导航 前言一、什么是调试器二、详解 GDB - 调试器1.使用前提2.经常使用的命令3.使用小技巧 三、项目自动化构建工具 - make/Makefile1. make命令⭕语法⭕常用选项⭕常用操作⭕make命令的工作原理⭕make命令的优势: 2.Makefile文件⭕Makefile的基本结构⭕Makefil…...

echarts-convert.js使用

echarts-convert.js demo 点击下载 1、本地安装phantom.js插件 window版本下载 2、更改文件路径 (D:\phantomjs-2.1.1-windows\bin)改为本地项目文件路径 3、打开cmd命令行,并格式化语言 运行以下命令 将命令行语言改为中文简体 chcp…...

数据结构之队列详解(包含例题)

一、队列的概念 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操…...

Prometheus的搭建与使用

一、安装Prometheus 官网下载地址:Download | Prometheus 解压:tar -zxvf prometheus-2.19.2.linux-amd64.tar.gz重命名: mv prometheus-2.19.2.linux-amd64 /home/prometheus进入对应目录: cd /home/prometheus查看配置文件&am…...

实战指南,SpringBoot + Mybatis 如何对接多数据源

系列文章目录 MyBatis缓存原理 Mybatis plugin 的使用及原理 MyBatisSpringboot 启动到SQL执行全流程 数据库操作不再困难,MyBatis动态Sql标签解析 从零开始,手把手教你搭建Spring Boot后台工程并说明 Spring框架与SpringBoot的关联与区别 Spring监听器…...

论文阅读——Imperceptible Adversarial Attack via Invertible Neural Networks

Imperceptible Adversarial Attack via Invertible Neural Networks 作者:Zihan Chen, Ziyue Wang, Junjie Huang*, Wentao Zhao, Xiao Liu, Dejian Guan 解决的问题:虽然视觉不可感知性是对抗性示例的理想特性,但传统的对抗性攻击仍然会产…...

List和ObservableCollection和ListBinding在MVVM模式下的对比

List和ObservableCollection和ListBinding在MVVM模式下的对比 List 当对List进行增删操作后,并不会对View进行通知。 //Employee public class Employee : INotifyPropertyChanged {public event PropertyChangedEventHandler? PropertyChanged;public string N…...

insightface安装过程中提示 Microsoft Visual C++ 14.0 or greater is required.

pip install insightface安装过程中提示 Microsoft Visual C 14.0 or greater is required.Get it with "Microsoft C Build Tools": https://visualstudio.microsoft.com/visual-cpp-build-tools/ 根据提示网站访问官网下载生成工具 打开软件后会自动更新环境&#…...

mongodb数据库

目录 一、数据库 二、文档 三、集合 四、元数据 五、MongoDB 数据类型 1、ObjectId 2、字符串 3、时间戳 4、日期 一、数据库 一个 mongodb 中可以建立多个数据库。 MongoDB 的默认数据库为"db",该数据库存储在 data 目录中。 MongoDB 的单…...

OpenCV-Python中的图像处理-图像特征

OpenCV-Python中的图像处理-图像特征 图像特征Harris角点检测亚像素级精度的角点检测Shi-Tomasi角点检测SIFT(Scale-Invariant Feature Transfrom)SURF(Speeded-Up Robust Features)FAST算法BRIEF(Binary Robust Independent Elementary Features)算法ORB (Oriented FAST and R…...

Ajax入门+aixos+HTTP协议

一.Ajax入门 概念:AJAX是浏览器与服务器进行数据通信的技术 axios使用: 引入axios.js使用axios函数:传入配置对象,再用.then回调函数接受结果,并做后续处理 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>01.axios使用…...

conda创建虚拟环境

创建虚拟环境是在计算机上设置一个独立的空间&#xff0c;用于安装和运行特定版本的软件和依赖项&#xff0c;以避免与系统其他部分的冲突。 创建虚拟环境&#xff1a; conda create --name myenv python3.8 这将创建一个名为myenv的虚拟环境&#xff0c;并安装Python 3.8版本。…...

Golang服务的请求调度

文章目录 1. 写在前面2. SheddingHandler的实现原理3. 相关方案的对比4. 小结 1. 写在前面 最近在看相关的Go服务的请求调度的时候&#xff0c;发现在gin中默认提供的中间件中&#xff0c;不含有请求调度相关的逻辑中间件&#xff0c;去github查看了一些服务框架&#xff0c;发…...

Jenkins的流水线启动jar后未执行问题处理

现象 在流水线里配置了启动脚本例如&#xff0c;nohup java -jar xxx.jar >nohup.out 2>&1 & 但是在服务器发现服务并未启动,且nohup日志里没输出日志,这样的原因是jenkins在执行完脚本后&#xff0c;就退出了这个进程。 在启动脚本执行jar命令的上一步加入以下…...

智慧工地平台工地人员管理系统 可视化大数据智能云平台源码

智慧工地概述&#xff1a; 智慧工地管理平台是以物联网、移动互联网技术为基础&#xff0c;充分应用大数据、人工智能、移动通讯、云计算等信息技术&#xff0c;利用前端信息采通过人机交互、感知、决策、执行和反馈等&#xff0c;实现对工程项目內人员、车辆、安全、设备、材…...

外包干了2个月测试,技术退步明显...

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...

神经网络基础-神经网络补充概念-19-向量化实现的解释

概念 向量化是一种优化技术&#xff0c;通过使用数组操作代替显式的循环&#xff0c;可以大大提高代码的性能和效率。在机器学习和数据分析领域&#xff0c;向量化是一种常见的实践&#xff0c;它允许你在处理大量数据时更快地进行计算。 一般操作 数组操作&#xff1a;向量…...

从PLC到Kubernetes:工业Python网关高可用配置的6层安全加固体系(含CVE-2024-XXXX漏洞规避方案)

第一章&#xff1a;工业Python网关的演进逻辑与高可用本质工业现场设备协议繁杂、环境严苛、响应实时性要求高&#xff0c;传统嵌入式网关受限于固件封闭、扩展能力弱和生态割裂&#xff0c;难以支撑现代智能制造对数据柔性接入与边缘智能协同的需求。Python凭借其丰富的工业协…...

AI人脸隐私卫士效果展示:看它如何精准识别并模糊多人合照

AI人脸隐私卫士效果展示&#xff1a;看它如何精准识别并模糊多人合照 1. 效果展示&#xff1a;从家庭合影到百人合照 1.1 家庭聚会照片处理 想象一下这样的场景&#xff1a;你刚刚参加完一场热闹的家庭聚会&#xff0c;手机里存满了欢乐的合影。这些照片中&#xff0c;有近景…...

AcousticSense AI避坑指南:常见问题解决,确保你的音乐识别流程顺畅运行

AcousticSense AI避坑指南&#xff1a;常见问题解决&#xff0c;确保你的音乐识别流程顺畅运行 关键词&#xff1a;AcousticSense AI、音乐流派识别、问题排查、音频处理、ViT模型、梅尔频谱图、故障解决、部署指南 摘要&#xff1a;部署AcousticSense AI进行音乐流派识别时&…...

揭秘新篇!AI应用架构师的数据安全服务AI防护新思路

揭秘新篇&#xff01;AI应用架构师的数据安全服务AI防护新思路 一、引言&#xff1a;AI时代的数据安全困局 当我们谈论AI应用时&#xff0c;数据是一切的核心——它是模型训练的“燃料”&#xff0c;是推理决策的“依据”&#xff0c;更是企业的核心资产。但随着AI技术的普及&a…...

Keil开发中printf重定向的常见陷阱与高效配置指南

1. 为什么你的printf在Keil里"装死"&#xff1f; 第一次在Keil里用printf的新手&#xff0c;八成会遇到这样的灵异事件&#xff1a;明明代码逻辑没问题&#xff0c;烧录后串口助手却像黑洞一样安静。我当年调试STM32F103时&#xff0c;整整两天都在和这个"哑巴&…...

Go gRPC 双向流通信实例

Go gRPC双向流通信实例解析 在现代分布式系统中&#xff0c;高效的双向通信是核心需求之一。gRPC作为Google开源的高性能RPC框架&#xff0c;支持双向流通信模式&#xff0c;允许客户端和服务端同时发送和接收多条消息。本文将以Go语言为例&#xff0c;介绍gRPC双向流通信的实…...

Path of Building:流放之路构筑规划的精准导航工具

Path of Building&#xff1a;流放之路构筑规划的精准导航工具 【免费下载链接】PathOfBuilding Offline build planner for Path of Exile. 项目地址: https://gitcode.com/gh_mirrors/pat/PathOfBuilding 在《流放之路》复杂多变的角色构建世界中&#xff0c;Path of …...

29、【Agent】【OpenCode】模型配置(OpenCode Zen)(二)

【声明】本博客所有内容均为个人业余时间创作&#xff0c;所述技术案例均来自公开开源项目&#xff08;如Github&#xff0c;Apache基金会&#xff09;&#xff0c;不涉及任何企业机密或未公开技术&#xff0c;如有侵权请联系删除 背景 上篇 blog 【Agent】【OpenCode】模型配…...

操作系统原理与LiuJuan20260223Zimage性能优化深度解析

操作系统原理与LiuJuan20260223Zimage性能优化深度解析 1. 引言 在AI模型部署和推理过程中&#xff0c;很多人只关注算法本身的优化&#xff0c;却忽略了底层操作系统对性能的关键影响。实际上&#xff0c;操作系统的资源管理策略、内存分配机制和进程调度方式&#xff0c;直…...

为什么FNF PsychEngine能成为节奏游戏创作的首选工具?

为什么FNF PsychEngine能成为节奏游戏创作的首选工具&#xff1f; 【免费下载链接】FNF-PsychEngine Engine originally used on Mind Games mod 项目地址: https://gitcode.com/gh_mirrors/fn/FNF-PsychEngine 如果你对Friday Night Funkin&#xff08;FNF&#xff09;…...