Redis入门到入坑14——发布订阅

2023年 9月 6日 63.2k 0

Redis 入门到入坑14——发布订阅

Redis发布/订阅模式

简介

Redis发布订阅(Pub/Sub)是一种消息传递模式,它允许发送消息的进程(发布者)向特定的接收消息的进程(订阅者)传递消息。在Redis中,发布者和订阅者都可以通过频道(channel)来发送和接收消息。

  • 发布者:发布者向指定的频道发送消息。发布者可以发送各种类型的消息,例如字符串、哈希、列表等。

  • 订阅者:订阅者订阅一个或多个频道,并接收这些频道中的消息。订阅者可以同时订阅多个频道,以接收不同类型的信息。

  • 频道:频道是发布者和订阅者之间的通信媒介。发布者将消息发送到特定的频道,订阅者从这些频道接收消息。

  • 持久化:Redis的发布订阅是持久化的,即使订阅者在消息发送时不在线,当订阅者再次连接时,它可以获取所有未接收的消息

下图展示了频道与订阅者的关系以及新消息发布时的流程
image.png

Redis 发布/订阅模式的工作流程

  • 发布者向一个或多个频道发送消息。
  • Redis将消息存储在内部缓冲区中,等待订阅者订阅相应的频道。
  • 订阅者通过SUBSCRIBE命令订阅一个或多个频道。
  • 当有消息发送到已订阅的频道时,Redis将消息发送给订阅者。
  • 订阅者可以通过UNSUBSCRIBE命令取消订阅某个频道,不再接收该频道的消息
  • 发布订阅模式的常用命令

    • SUBSCRIBE channel [channel ...]
      :订阅指定的一个或者多个频道(推荐先执行订阅之后再发布,订阅成功之前发布的消息是接收不到的)
    127.0.0.1:6379> subscribe c1
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "c1"
    3) (integer) 1
    
    • PUBLISH channel message:将消息发送到指定的频道
    --- 发布消息的客户端
    [root@gone ~]# redis-cli
    127.0.0.1:6379> publish c1 hello_c1
    (integer) 2
    
    --- 之前订阅消息的客户端
    127.0.0.1:6379> subscribe c1 
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "c1"
    3) (integer) 1
    1) "message"         ------- 消息的种类
    2) "c1"              ------- 始发频道的名称
    3) "hello_c1"        ------- 实际的消息内容
    
    • PSUBSCRIBE [pattern [pattern ...]]:订阅一个或多个符合给定模式的频道
    -- 这个命令订阅了所有以 "redis1" 开头和以 "redis2" 开头的频道,并输出多条显示订阅成功的消息
    PSUBSCRIBE redis1* redis2* 
    
    • PUBSUB [argument [argument ...]]]:查看订阅与发布系统状态。它由数个不同格式的子命令组成

    --- 返回活跃频道的列表
    127.0.0.1:6379> pubsub channels
    1) "c1"
    2) "c2"
    --- 返回c1频道的订阅者数量
    127.0.0.1:6379> pubsub numsub c1
    1) "c1"
    2) (integer) 3
    -- 只统计使用PSUBSCRIBE命令执行的,返回客户端订阅的唯—模式的数量
    --- 客户端1下执行
    127.0.0.1:6379> psubscribe a* b* c* d*
    Reading messages... (press Ctrl-C to quit)
    1) "psubscribe"
    2) "a*"
    3) (integer) 1
    1) "psubscribe"
    2) "b*"
    3) (integer) 2
    1) "psubscribe"
    2) "c*"
    3) (integer) 3
    1) "psubscribe"
    2) "d*"
    3) (integer) 4
    --- 客户端2下执行
    127.0.0.1:6379> pubsub numpat
    (integer) 4
    
    • PUNSUBSCRIBE [pattern [pattern ...]]:退订所有给定模式的频道

    --- 命令退订了所有以"redis1"开头和以"redis2"开头的频道,并输出多条显示退订成功的消息
    PUNSUBSCRIBE redis1* redis2*
        
    
    • UNSUBSCRIBE [channel ...]:取消订阅指定的频道
    127.0.0.1:6379> unsubscribe c1
    1) "unsubscribe"
    2) "c1"
    3) (integer) 0    
    

    案例演示

    • 开启3个客户端,客户端A、B订阅消息,C发布消息
    --- 1.客户端A订阅:
    127.0.0.1:6379> subscribe c1 
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "c1"
    3) (integer) 1    
    
    --- 2.客户端B订阅
    127.0.0.1:6379> subscribe c1 
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "c1"
    3) (integer) 1 
    
    --- 3.客户端C发布
    127.0.0.1:6379> publish c1 'hello channel c1'
    (integer) 2 
    
    --- 4.查看客户端A
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "c1"
    3) (integer) 1
    1) "message"
    2) "c1"
    3) "hello channel c1"
        
    --- 5.查看客户端B
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "c1"
    3) (integer) 1
    1) "message"
    2) "c1"
    3) "hello channel c1"
    
    • 批量订阅和发布
    --- 批量订阅
    --- 1.客户端A执行
    127.0.0.1:6379> psubscribe a* b* c* d*
    Reading messages... (press Ctrl-C to quit)
    1) "psubscribe"
    2) "a*"
    3) (integer) 1
    1) "psubscribe"
    2) "b*"
    3) (integer) 2
    1) "psubscribe"
    2) "c*"
    3) (integer) 3
    1) "psubscribe"
    2) "d*"
    3) (integer) 4
    
    ---2.客户端B执行
    127.0.0.1:6379> pubsub numpat
    (integer) 4
    127.0.0.1:6379> publish c10 hello_channel_c10
    (integer) 1
    127.0.0.1:6379> publish a11 hello_channel_a11
    (integer) 1
    
    --- 3.查看客户端A的信息输出
    127.0.0.1:6379> psubscribe a* b* c* d*
    Reading messages... (press Ctrl-C to quit)
    1) "psubscribe"
    2) "a*"
    3) (integer) 1
    1) "psubscribe"
    2) "b*"
    3) (integer) 2
    1) "psubscribe"
    2) "c*"
    3) (integer) 3
    1) "psubscribe"
    2) "d*"
    3) (integer) 4
        
    ---- 输出的信息
    1) "pmessage"
    2) "c*"
    3) "c10"
    4) "hello_channel_c10"
    1) "pmessage"
    2) "a*"
    3) "a11"
    4) "hello_channel_a11"
    

    发布订阅模式的缺点

    Redis 的发布-订阅模式是一种非常强大的消息传递机制,它允许订阅者监听一个或多个频道,并在有消息发布到这些频道时接收它们。然而,这种模式也有一些潜在的缺点:

  • 消息可靠性:在 Redis 的发布订阅模型中,消息是单向传输的。发布者将消息发布到一个通道(channel),然后所有订阅该通道的订阅者都会收到消息。然而,一旦消息被发布,Redis 不提供任何确保消息到达的机制。如果订阅者在消息发布时离线或者处理消息失败,那么消息可能会丢失。
  • 消息传递的持久性:Redis 的发布订阅模型不保证消息的持久性。如果订阅者在消息发布后关闭或者崩溃,那么消息可能会丢失。为了解决这个问题,可以配置 Redis 持久化消息,但这样会增加额外的性能开销和存储需求。
  • 消息的顺序性:在 Redis 的发布订阅模型中,多个订阅者可以同时接收到发布者发布的消息。然而,无法保证消息的顺序性。即,不同的订阅者可能会以不同的顺序接收到同样的一系列消息。如果需要严格的消息顺序性,可能需要额外的逻辑来处理。
  • 消息的确认机制:在 Redis 的发布订阅模型中,没有内置的消息确认机制。当订阅者接收到消息后,它不会向发布者发送确认消息。这可能导致发布者无法确定消息是否成功传递给所有订阅者。为了解决这个问题,可以引入一个确认机制,但会增加系统的复杂性。
  • 性能和资源利用:在大量并发订阅者和发布者的情况下,Redis 的发布订阅模型可能会对系统性能和资源利用产生影响。为了处理大量的订阅者和发布者,可能需要增加更多的 Redis 实例和网络带宽。此外,如果每个订阅者都接收所有发布的消息,可能会导致大量的网络流量和内存消耗。
  • 相关文章

    JavaScript2024新功能:Object.groupBy、正则表达式v标志
    PHP trim 函数对多字节字符的使用和限制
    新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
    使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
    为React 19做准备:WordPress 6.6用户指南
    如何删除WordPress中的所有评论

    发布评论