• 6. Redis 发布与订阅


    6. Redis 发布与订阅

    参考地址:https://blog.csdn.net/w15558056319/article/details/121490953

    Redis的发布与订阅功能可以让客户端通过广播方式,将 消息(message)同时发送给可能存在的多个客户端,并且发送消息的客户端不需要知道接收消息的客户端的具体信息。换句话说,发布消息的客户端与接收消息的客户端两者之间没有直接联系。

    在Redis中,客户端可以通过订阅特定的 频道(channel)来接收发送至该频道的消息,我们把这些订阅频道的客户端称为订阅者(subscriber)。一个频道可以有任意多个订阅者,而一个订阅者也可以同时订阅任意多个频道。除此之外,客户端还可以通过向频道发送消息的方式,将消息发送给频道的所有订阅者,我们把这些发送消息的客户端称为发送者(publisher)。

    发布订阅的实现场景

    1、实时沟通消息系统

    2、微信公众号(点击关注,后台发送一篇博客,订阅的用户就可以监听到)

    3、电商中,用户下单成功之后向指定频道发送消息,下游业务订阅支付结果这个频道处理自己相关业务逻辑

    4、粉丝关注功能、文章推送

    还有一些比较复杂的场景,可以使用消息中间件来做,kafka RabbitMQ ActiveMQ RocketMQ …等

    在这里插入图片描述

    示例:

    有三个客户端订阅了一个 Channel1

    在这里插入图片描述

    当 Channel1 的后台发送了一个数据到 Channel1 的频道中,这三个订阅了 Channel1 的客户端就会同时收到这个数据
    在这里插入图片描述

    为什么需要发布、订阅

    redisList 数据类型结构提供了 blpop 、brpop 命令结合 rpush、lpush 命令可以实现消息队列机制,基于双端链表实现的发布与订阅功能

    • 这种方式存在两个局限性:
    1. 不能支持一对多的消息分发。
    2. 如果生产者生成的速度远远大于消费者消费的速度,易堆积大量未消费的消息

    🔷双端队列图解如下:

    在这里插入图片描述

    解析: 双端队列模式只能有一个或多个消费者轮着去消费,却不能将消息同时发给其他消费者

    🔶发布/订阅模式图解如下:

    在这里插入图片描述

    解析: redis 订阅发布模式,生产者生产完消息通过频道分发消息,给订阅了该频道的所有消费

    发布/订阅如何使用?

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

    • 基于频道(Channel)的发布/订阅
    • 基于模式(pattern)的发布/订阅
    • 操作命令
    1. 基于频道
    命令描述
    subscribe channel [channel … ]订阅给定的一个或多个频道
    unsubscribe channel [channel … ]退订给定的频道,说明:若没有指定channel,则默认退订所有频道
    publish channel message将消息发送给指定频道 channel ,返回结果:接收到信息的订阅者数量,无订阅者返回0
    pubsub channels [argument [atgument …] ]查看订阅与发布系统的状态,说明:返回活跃频道列表(即至少有一个订阅者的频道,订阅模式的客户端除外)
    1. 基于模式
    命令描述
    psubscribe pattern1 [pattern…]订阅一个或多个符合给定模式的频道,说明:每个模式以 * 作为匹配符;例如 cn* 匹配所有以cn开头的频道:cn.java、cn.csdn
    punsubscribe [pattern [pattern …] ]退订所有给定模式的频道,说明:pattern 未指定,则订阅的所有模式都会被退订,否则只退订指定的订阅的模式

    1️⃣基于频道发布

    “发布/订阅” 包含2种角色:发布者和订阅者。
    发布者可以向指定的频道(channel)发送消息;
    订阅者可以订阅一个或者多个频道(channel),所有订阅此频道的订阅者都会收到此消息。

    在这里插入图片描述

    SUBSCRIBE:频道订阅

    用户可以通过执行 SUBSCRIBE 命令,让客户端订阅给定的一个或多个频道。

    # 示例:
    127.0.0.1:6379> SUBSCRIBE news
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"		返回值类型:表示订阅成功!
    2) "news"			订阅频道的名称
    3) (integer) 1		当前客户端已订阅频道的数量
    
    # 语法解析:
    subscribe		订阅命令
    news			订阅频道
    
    # 注意:订阅后,该客户端会一直监听消息,如果发送者有消息发给频道,这里会立刻接收到消息
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意:进入订阅状态的客户端,不能使用除了 subscribe、unsubscribe、psubscribe 和 punsubscribe 这四个属于"发布/订阅"之外的命令,否则会报错!

    ——这里的客户端指的是 jedis、lettuce 的客户端,redis-cli 是无法退出订阅状态的!

    PUBLISH:向频道发送消息

    用户可以通过执行 PUBLISH 命令,将一条消息发送至给定频道

    # 示例:
    127.0.0.1:6379> PUBLISH news "hello world"
    (integer) 1			# 接收到信息的订阅者数量,无订阅者返回0
    127.0.0.1:6379> 
    
    # 语法解析:
    publish			命令
    news			订阅频道名
    hello world		消息内容
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    UNSUBSCRIBE:退订频道

    用户在使用 SUBSCRIBE 命令订阅一个或多个频道之后,如果不想再收到某个频道的消息,那么可以使用 UNSUBSCRIBE 命令退订指定的频道。

    UNSUBSCRIBE 命令允许用户给定任意多个频道。如果用户没有给定任何频道,直接以无参数方式执行 UNSUBSCRIBE 命令,那么命令将退订当前客户端已经订阅的所有频道。

    2️⃣ 基于模式(pattern)的发布/订阅

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

    图解

    下图展示了一个带有频道和模式的例子, 其中 com.ahead.\* 频道匹配了 com.ahead.juc 频道和 com.ahead.thread 频道, 并且有不同的客户端分别订阅它们三个,如下图:

    当有信息发送到 com.ahead.thread 频道时, 信息除了发送给 client 4client 5 之外, 还会发送给订阅 com.ahead.* 频道模式的 client xclient y

    在这里插入图片描述

    🔷 解析:

    反之也是,如果当有消息发送给 com.ahead.juc 频道,消息发送给订阅了 juc 频道的客户端之外,还会发送给订阅了 com.ahead.* 频道的客户端: client x 、client y

    🔶 注意:

    通配符中 ? 表示1个占位符

    * 表示任意个占位符(包括0)

    ?* 表示1个以上占位符。

    PSUBSCRIBE:模式订阅

    用户可以通过执行 PSUBSCRIBE 命令,让客户端订阅给定的一个或多个模式。

    # 示例:
    127.0.0.1:6379> PSUBSCRIBE a? news.*			# 订阅 “a?” "com.*" 2种模式频道
    Reading messages... (press Ctrl-C to quit)		# 进入订阅状态后处于阻塞,可以按Ctrl+C键退出订阅状态
    1) "psubscribe"			返回值的类型:显示订阅成功
    2) "a?"					订阅的模式
    3) (integer) 1			目前已订阅的模式的数量
    
    1) "psubscribe"
    2) "news.*"
    3) (integer) 2
    
    1) "pmessage"			返回值的类型:信息
    2) "a?"					信息匹配的模式:a?
    3) "ab"					信息本身的目标频道:aa
    4) "hello world"		信息的内容:"hello world"
    
    1) "pmessage"
    2) "news.*"
    3) "news.dbname"
    4) "redis mysql oracle"
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    PUBLISH:模式发布

    # 示例:
    # 发布者第一条命令
    # 结果:没有接收到消息,匹配失败,不满足 “a?” ,“?”表示一个占位符, a后面的sdf有3个占位符
    127.0.0.1:6379> PUBLISH asdf "hello world"
    (integer) 0
    
    # 发布者第二条命令,匹配到一个订阅
    127.0.0.1:6379> PUBLISH ab "hello world"
    (integer) 1
    
    # 发布者第二条命令,news.dbname 满足 new.* 匹配规则
    127.0.0.1:6379> PUBLISH news.dbname "redis mysql oracle"
    (integer) 1
    127.0.0.1:6379> 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    PUNSUBSCRIBE:退订模式

    与退订频道的 UNSUBSCRIBE 命令类似,Redis 也提供了用于退订模式的 PUNSUBSCRIBE 命令

    PUNSUBSCRIBE [pattern [pattern ...]]
    # 示例:
    PUNSUBSCRIBE news.*
    
    • 1
    • 2
    • 3
    • 如果用户没有给定任何模式,那么命令将退订当前客户端已订阅的所有模式。

    UNSUBSCRIBE 命令一样,各个客户端对于 PUNSUBSCRIBE 命令的需求也是不同的,有些客户端需要用到PUNSUBSCRIBE 命令,而有些客户端则不需要。

    例如:

    Redis自带的命令行客户端 redis-cli 在执行 PSUBSCRIBE 命令之后就会进入阻塞状态,只能通过同时按下Ctrl键和C键来退出程序,因此它并不需要用到 PUNSUBSCRIBE 命令。

    查看被订阅的频道

    用户可以通过执行 PUBSUB CHANNELS 命令来列出目前被订阅的所有频道,如果给定了可选的 pattern 参数,那么命令只会列出与给定模式相匹配的频道。

    PUBSUB CHANNELS [pattern]
    
    # 示例:
    127.0.0.1:6379> PUBSUB CHANNELS
    
    127.0.0.1:6379> PUBSUB CHANNELS news.*
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    查看频道的订阅者数量

    用户可以通过执行 PUBSUB NUMSUB 命令,查看任意多个给定频道的订阅者数量

    PUBSUB NUMSUB [channel [channel ...]]
    # 示例:
    PUBSUB NUMSUB news.dbname
    1) "news.dbname"
    2) (integer) 2		频道订阅数量
    
    • 1
    • 2
    • 3
    • 4
    • 5

    查看被订阅模式的总数量

    通过执行 PUBSUB NUMPAT 命令,用户可以看到目前被订阅模式的总数量

    # 示例:
    127.0.0.1:6379> PUBSUB NUMPAT
    (integer) 2
    
    • 1
    • 2
    • 3

    3️⃣ 使用注意

    • 客户端需要及时消费和处理消息。

      客户端订阅了 channel 之后,如果接收消息不及时,可能导致 DCS 实例消息堆积,当达到消息堆积阈值(默认值为32MB),或者达到某种程度(默认8MB)一段时间(默认为1分钟)后,服务器端会自动断开该客户端连接,避免导致内部内存耗尽。

    • 客户端需要支持重连。

      当连接断开之后,客户端需要使用 subscribe 或者 psubscribe 重新进行订阅,否则无法继续接收消息。

    • 不建议用于消息可靠性要求高的场景中。

      Redis的 pubsub 不是一种可靠的消息系统。当出现客户端连接退出,或者极端情况下服务端发生主备切换时,未消费的消息会被丢弃。

     
     
     
     
     

  • 相关阅读:
    网页前端设计-作业三(JavaScript)
    EPS功能开发与测试(基于ModelBase实现)
    〖Python 数据库开发实战 - Redis篇④〗- Redis命令行客户端与图形客户端的简单使用
    前端进击笔记第二十一节 如何搭建前端监控体系为业务排忧解难?
    android dex 优化
    指针的进阶应用之双指针、三指针
    cherry-pick
    阿里双十一交易核心链路产品--RocketMQ 底层原理及性能调优实战
    pytest + yaml 框架 -62.支持yaml和json2种格式用例
    C#经典十大排序算法(完结)
  • 原文地址:https://blog.csdn.net/D1179869625/article/details/125465098