Redis:发布订阅机制

article/2025/9/11 9:19:01

参考资料:

《Redis进阶——发布订阅详解》

《Redis 发布订阅》

《Redis进阶 - 消息传递:发布订阅模式详解》

        写在开头:本文为学习后的总结,可能有不到位的地方,错误的地方,欢迎各位指正。

目录

一、什么是发布订阅

二、发布订阅的实现

        1、基于频道的发布订阅

        (1)使用方法

        (2)具体实现

        2、基于模式的发布订阅

        (1)使用方法

        (2) 具体实现

补充

        退订

        发布订阅实际应用


一、什么是发布订阅

        Redis的发布订阅实现了类似mq的消息推送功能。

        假设我们有一个支付接口,在这个接口中,又要去调用其他三个服务。

        

        我们可能会使用上图这样线性调用的方法来执行,但这样的设计会带来几个问题:

  • 下单支付业务与其他业务重度耦合,每当有个新业务需要支付结果,就需要改动下单支付的业务
  • 如果调用业务过多,会导致下单支付接口响应时间变长。另外,如果有任一下游接口响应变慢,就会同步导致下单支付接口响应也变长
  • 如果任一下游接口失败,可能导致数据不一致的情况。比如说下图,先调用 A,成功之后再调用 B,最后再调用 C,当B失败了,就会导致数据不一致

        为此,我们希望能够将这几个功能模块进行拆分、解耦,于是我们便想到了使用中间件消息推送,当支付接口被调用时,利用这个机制通知另外三个服务进行处理。当然,我们可以使用专业的mq如rabbitmq等来实现这个功能,不过Redis也能实现相同的效果,这就是它的发布/订阅机制。        

         发布订阅机制包含2个对象,发布者和订阅者,当两者建立发布订阅关系后,当发布者向redis中发布消息时,订阅者就能收到这个消息,就像上面的业务场景,支付接口只需要向特定频道发送消息,其他下游业务订阅这个频道,就能收相应消息,然后做出业务处理即可

二、发布订阅的实现

        1、基于频道的发布订阅

        (1)使用方法

        在Redis中,我们使用subscribe指令指定当前客户端订阅的频道,一个订阅者可以订阅多个频道,这个频道如果不存在则会先进性创建。

# subscribe channel  [channel ... ]
# 订阅给定的一个或多个频道127.0.0.1:6379> subscribe meihuashisan meihuashisan2 
Reading messages... (press Ctrl-C to quit)1) "subscribe"    -- 返回值类型:表示订阅成功!
2) "meihuashisan" -- 订阅频道的名称
3) (integer) 1    -- 当前客户端已订阅频道的数量1) "subscribe"
2) "meihuashisan2"
3) (integer) 2

         发布者则使用publish向某个频道发布消息。

# 格式为publish channel message 
# 将消息发送给指定频道 channel
# 返回结果:接收到信息的订阅者数量,无订阅者返回0127.0.0.1:6379> publish meihuashisan "I am meihuashisan"
(integer) 1  # 接收到信息的订阅者数量,无订阅者返回0

        当发布者发布消息后,订阅了该频道的客户端就会收到该条消息。 

127.0.0.1:6379> subscribe meihuashisan csdn 
Reading messages... (press Ctrl-C to quit)1) "subscribe"    -- 返回值类型:表示订阅成功!
2) "meihuashisan" -- 订阅频道的名称
3) (integer) 1    -- 当前客户端已订阅频道的数量1) "subscribe"
2) "csdn"
3) (integer) 2---------------------追加变化如下:(实时接收到了该频道的发布者的消息)------------1) "message"           -- 返回值类型:消息
2) "meihuashisan"      -- 来源(从哪个频道发过来的)
3) "I am meihuashisan" -- 消息内容

        (2)具体实现

        在redisServer中,有一个字典类型的字段pubsub_channels,用来保存订阅信息,其中key为频道,value为订阅该频道的客户端

struct redisServer { /* General */ pid_t pid; //其他省略...// 将频道映射到已订阅客户端的列表(就是保存客户端和订阅的频道信息)dict *pubsub_channels; /* Map channels to list of subscribed clients */ 
}

 ​​​​​​​        ​​​​​​​如下图的这个示例中, client1 、 client2订阅了 channel_1 , 而其他频道也分别被别的客户端所订阅。

        当客户端 client7执行命令subscribe channel1 channel2 channel3 ,那么就会把这个客户端分别加到相应key的链表末尾。

         当调用 publish channel message 命令, 程序首先根据 channel 定位到字典的键, 然后将信息发送给字典值链表中的所有客户端。 以上图为例, 如果某个客户端执行命令 PUBLISH channel1 "hello moto" ,那么 client2 、 client5 和 client1 三个客户端都将接收到 "hello moto" 信息。

 

        2、基于模式的发布订阅

        (1)使用方法

        在基于频道的订阅中,我们通过输入某个频道的完整名称来实现订阅,而基于模式的订阅在使用时不需要指定全名,而是使用一个模式匹配字符串代替,当与该模式匹配的频道有消息发布时,就可以接收到。

        在模式匹配中,通配符中?表示1个占位符,*表示任意个占位符(包括0),?*表示1个以上占位符。例如tweet.shop.*能匹配tweet.shop.ipad和tweet.shop.kindle。

        如下图,client123与client256通过基于模式的发布订阅接收与tweet.shop.*模式匹配的频道的消息。因此当tweet.shop.ipad和tweet.shop.kindle频道有消息发布时,client123与client256都能接收到。

 

        订阅者通过psubscribe pattern  [pattern ...] 进行模式订阅。

#  订阅 “a?” "com.*" 2种模式频道(注意中间的空格表明这是2个模式)
127.0.0.1:6379> psubscribe a? com.*
# 进入订阅状态后处于阻塞,可以按Ctrl+C键退出订阅状态
Reading messages... (press Ctrl-C to quit) 1) "psubscribe"  -- 返回值的类型:显示订阅成功
2) "a?"          -- 订阅的模式
3) (integer) 1   -- 目前已订阅的模式的数量1) "psubscribe"
2) "com.*"
3) (integer) 2# 接收消息 (已订阅 “a?” "com.*" 两种模式!)# ---- 发布者第1条命令: publish ahead "hello"
结果:没有接收到消息,匹配失败,不满足 “a?” ,“?”表示一个占位符, a后面的head有4个占位符# 发布者第2条命令:  publish aa "hello" (满足 “a?”)
1) "pmessage" -- 返回值的类型:信息
2) "a?"       -- 信息匹配的模式:a?
3) "aa"       -- 信息本身的目标频道:aa
4) "hello"    -- 信息的内容:"hello"# 发布者第3条命令:publish com.juc "hello2"(满足 “com.*”, *表示任意个占位符)
1) "pmessage" -- 返回值的类型:信息
2) "com.*"    -- 匹配模式:com.*
3) "com.juc"  -- 实际频道:com.juc
4) "hello2"   -- 信息:"hello2"# 发布者第4条命令: publish com. "hello3"(满足 “com.*”, *表示任意个占位符)
1) "pmessage" -- 返回值的类型:信息
2) "com.*"    -- 匹配模式:com.*
3) "com."     -- 实际频道:com.
4) "hello3"   -- 信息:"hello3"

         发布者还是通过publish channel message发布消息。

# 1. ahead 不符合“a?”模式,?表示1个占位符
127.0.0.1:6379> publish ahead "hello"  
(integer) 0    -- 匹配失败,0:无订阅者# 2. aa 符合“a?”模式,?表示1个占位符
127.0.0.1:6379> publish aa "hello"      
(integer) 1# 3. 符合“com.*”模式,*表示任意个占位符
127.0.0.1:6379> publish com.juc "hello2" 
(integer) 1# 4. 符合“com.*”模式,*表示任意个占位符
127.0.0.1:6379> publish com. "hello3" 
(integer) 1

        (2) 具体实现

        在redisServer中有一个pubsub_patterns属性,该属性表示一个链表,链表中保存着所有和模式相关的信息。

struct redisServer {//...list *pubsub_patterns; // ...
}

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

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

        最终实现即如下图所示

         当有新的模式订阅者时,就将这个客户端分别加入到该模式的client中。

补充

        退订

        如要退订某个频道或模式,可使用如下指令:

  • UNSUBSCRIBE    UNSUBSCRIBE [channel [channel ...]]—取消订阅指定频道。
  • PUNSUBSCRIBE    PUNSUBSCRIBE [pattern [pattern ...]]—取消订阅符合指定模式的频道。

        发布订阅实际应用(待补充)

        Redis Sentinel 节点发现
        Redission 分布式锁​​​​​​​

        

        


http://chatgpt.dhexx.cn/article/waaJhVXG.shtml

相关文章

redis发布订阅

目录 一、概要 二、特点 三、发布及订阅功能 四、Redis发布订阅命令 五、php实现redis发布-订阅 1、消息发布端 2、消息订阅端 六、订阅发布使用场景 七、在订阅时遇到错误 八、模式匹配(正则匹配)订阅 一、概要 Redis发布订阅(pub/sub)是一种…

springboot 整合使用redis发布订阅功能

前言 发布订阅作为一种设计思想在很多开源组件中都有体现,比如大家熟知的消息中间件等,可谓把发布订阅这一思想体现的淋漓尽致了; 一、redis发布订阅简介 Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收信息。可以参考下面两张图进…

Redis进阶——发布订阅详解

什么是发布订阅? Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。 Redis 的 subscribe 命令可以让客户端订阅任意数量的频道, 每当有新信息发送到被订阅的频道时, 信息就会被发…

Redis 的发布与订阅

3、Redis 的发布与订阅 3.1、发布与订阅简述 Redis提供了基于“发布/订阅”模式的消息机制。此种模式下,消息发布者和订阅者不进行直接通信,发布者客户端向指定的频道(channel) 发布消息,订阅该频道的每个客户端都可…

6. Redis 发布与订阅

文章目录 6. Redis 发布与订阅为什么需要发布、订阅发布/订阅如何使用? :one:基于频道发布SUBSCRIBE:频道订阅PUBLISH:向频道发送消息UNSUBSCRIBE:退订频道 :two: 基于模式(pattern)的发布/订阅PSUBSCRIBE:模式订阅PUB…

Redis的发布订阅

Redis的发布订阅(pub/sub)是一种消息通信模式,发送者(pub)发送信息,订阅者(sub)接收信息。Redis客户端可以订阅任意数量的频道。Pub/Sub 从字面上理解就是发布(Publish&a…

Redis数据库的发布与订阅(详细讲解)

一、实验目的 了解Redis数据库的发布与订阅 二、发布与订阅 1.1什么是发布和订阅 发布订阅是一对多的关系,需要有信息的发布者和消息的收听者。 发布者:提供某个内容或主题,把内容信息发送给多个对此内容感兴趣的订阅者 订阅者&#xff…

Redis发布和订阅

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

Redis--发布订阅--原理/使用场景

原文网址:Redis--发布订阅--原理/使用场景_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Redis的发布订阅功能。 Redis发布订阅简述 Redis提供了基于“发布/订阅”模式的消息机制。此种模式下,消息发布者和订阅者不进行直接通信,发布者客户端…

php查netstat,netstat怎么查看端口状态

netstat查看端口状态的方法:首先打开终端命令窗口;然后通过命令“netstat -ntlp”查看当前所有tcp端口;最后通过“netstat -ntulp | grep 80”命令查看所有80端口使用情况即可。 本教程操作环境:linux5.9.8系统,DELL G…

Linux系统使用ss命令查看端口状态

Linux系统使用ss命令查看端口状态 Linux系统使用ss命令查看端口状态 目录 1.可用工具 2.ss帮助 2.1 选项分类说明 2.2 过滤选项family 2.3 过滤选项state 2.4 状态之间的关系 3.ss的使用 3.1 使用示例 3.2 过滤 3.2.1 状态过滤 3.2.2 通过family过滤 3.2.3 使用地址和端口过滤 …

Win7怎样查看端口状态

在Win7系统中,查看端口状态可以采用以下两种方法: 1.netstat 先单击“开始”,再单击“运行”,输入"cmd",进入DOS窗口。输入命令"netstat -na",按回车,就会显示本机连接情况…

Linux查看端口状态

在Linux使用过程中,需要了解当前系统开放了哪些端口,并且要查看开放这些端口的具体进程和用户,可以通过netstat命令进行简单查询 netstat命令各个参数说明如下: -t : 指明显示TCP端口   -u : 指明显示UDP端口   -l : 仅显示…

php 查看端口配置信息,查看端口状态的命令是什么

查看端口状态的命令是“netstat”,其语法是“netstat -ntlp”,netstat命令一般用于检验本机各端口的网络连接情况,netstat是在内核中访问网络及相关信息的程序,它能提供TCP连接,TCP和UDP监听等相关报告。 linux系统中查…

通过查看端口状态查看mongodb是否已经启动

LINUX环境下,可以通过查看端口27017的状态查看mongod是否已经启动。 netstat -lanp | grep "27017" 可以看到已经启动了mongod服务。 然后关闭mongod服务 sudo service mongod stop 可以看到端口状态发生了变化 再开启服务 sudo service mongod star…

Linux查看端口状态及 查看与其他主机的联通状态 命令

目录 netstat Telnet netstat 在Linux使用过程中,需要了解当前系统开放了哪些端口,并且要查看开放这些端口的具体进程和用户,可以通过netstat命令进行简单查询 netstat命令各个参数说明如下: -t : 指明显示TCP端口 -u : 指明…

Ubuntu开放端口及其查看端口开放状态

前言 在服务器部署应用的时候,我们经常要查看这个应用是否部署成功,而一般就是通过ip 端口的方式在浏览器上进行查看默认的一些页面是否出现当页面没有出现的情况下,不一定是应用没启动成功,可能是因为端口未开放出去&#xff0…

netstat查看端口状态

netstat(network status网络状态)命令各个参数说明如下: -t : 指明显示TCP端口,t是TCP的首字母。 -u : 指明显示UDP端口,u是UDP的首字母 -l : 仅显示监听套接字(所谓套接字就是使应用程序能够读写与收发通讯协议(proto…

Netstat查看端口状态,netstat命令详解

netstat命令详解 概述Netstat查看端口状态 概述 netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息。 Netstat查看端口状态 1、点击左下角的【开始】,找到运行,或是直接…

聊聊linux查看服务和端口状态命令netstat

使用netstat命令可以查看linux系统中正在使用的服务和端口情况 常见参数 -a (all)显示所有选项,默认不显示LISTEN相关 -t (tcp)仅显示tcp相关选项 -u (udp)仅显示udp相关选项 -n 拒绝显示别名,能显示数字的全部转化成数字。 -l 仅列出有在 Listen (监听…