• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 位置: redis 中文手册 -> redis 功能命令

    发布订阅(pub/sub)

    Redis发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis 客户端可以订阅任意数量的频道。

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


    实例演示

    演示了发布订阅是如何工作的。在我们实例中我们创建了订阅频道名为redisChat

    第一步:打开一个 redis 客户端,订阅频道 redisChat

    redis> SUBSCRIBE redisChat 
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "redisChat"
    3) (integer) 1
    

    第二步:另外再打开一个 redis 客户端,在频道redisChat上发布消息

    redis> PUBLISH redisChat "Redis is a great caching technique"
    (integer) 1
    
    redis> PUBLISH redisChat "Learn redis by w3cschool.cc" 
    (integer) 1
    

    第三步:查看第一次打开的 redis 客户端,会显示接受到的消息

    1) "message"
    2) "redisChat"
    3) "Redis is a great caching technique"
    
    1) "message"
    2) "redisChat"
    3) "Learn redis by w3cschool.cc" 
    



    发布订阅模式详解

    Redis发布/订阅(Pub/Sub)是一种通信机制,将数据推到某个信息管道中,其他客户端可通过订阅这些管道来获取推送信息,以此用于消息的传输。

    由三部分组成:发布者(Publisher)、频道(Channel)、订阅者(Subscriber)。

    发布者发布的消息分到不同的频道,不需要知道什么样的订阅者者订阅。订阅者对一个或多个频道感兴趣,只需要接收感兴趣的消息,不需要知道什么样的发布者发布。主要目的是解除消息的发布者与订阅者之间的耦合关系。发布者和订阅者都是Redis客户端,频道则是服务器端。

    原理

    Redis通过SUBSCRIBEPSUBSCRIBEUNSUBSCRIBEPUNSUBSCRIBE等命令实现发布和订阅功能。

    在Redis底层结构中,客户端和频道的订阅关系是通过一个字典加链表的结构保存的,如下图:

    在 Redis 的底层结构中,redis服务器中定义了一个pubsub_channels字典,用于保存所有频道的订阅关系,在这个字典中,key 为所有频道名称,value 结构是一个链表,其中存放的是所有订阅这个频道的订阅者客户端。subscribe 命令的实质即为在key中添加value的订阅链。若频道首次被订阅说明在字典中并不存在该渠道的信息,那么程序首先要新建一个对应的 key,并且要赋值一个空链表,然后将对应的客户端加入到链表中。此时链表只有一个元素。若该渠道已经被其他客户端订阅过:这个时候就直接找到key值对应的value客户端信息添加到链表的末尾即可。

    推送的消息格式

    所有订阅接收的消息均为由三个元素组成的多块响应。

    第一个元素是消息类型,有三种类型:

    • subscribe:该类型表示成功订阅到频道响应,此时第二个元素为订阅的频道名称,第三个元素为已订阅的频道数量,例:
      redis> SUBSCRIBE myChannel
      Reading messages... (press Ctrl-C to quit)
      1) "subscribe"
      2) "myChannel"
      3) (integer) 1
      
    • unsubscribe:该类型表示成功取消订阅到的频道响应,此时第二个元素为订阅的频道名称,第三个元素为已订阅的频道数量,例:
      redis> UNSUBSCRIBE myChannel
      1) "unsubscribe" 
      2) "myChannel"  
      3) (integer) 0
      
    • message:该类型表示订阅者客户端接收到其他客户端发出的发布命令结果,此时第二个元素表示来源频道的名称,第三个元素是实际的消息内容,例:
      redis> SUBSCRIBE myChannel myChannel2
      1) "subscribe" 
      2) "myChannel"  
      3) (integer) 1
      1) "subscribe"
      2) "myChannel2"
      3) (integer) 2
      1) "message"
      2) "myChannel1"
      


    发布订阅命令

    发送消息

    PUBLISH 命令为发送信息,返回值为接收到该消息的订阅者数量。

    redis> PUBLISH mychannel "Hello"
    (integer) 1
    
    redis> PUBLISH mychannel "World"
    (integer) 1
    

    订阅频道

    SUBSCRIBE命令为订阅频道,返回值消息格式如上所述。

    redis> SUBSCRIBE myChannel
    Reading messages... (press Ctrl-C to quit)
    1) "subscribe"
    2) "myChannel"
    3) (integer) 1
    1) "message"
    2) "myChannel"
    3) "Hello"
    1) "message"
    2) "myChannel"
    

    模式匹配

    PSUBSCRIBE命令订阅一个或多个符合给定模式的频道。每个模式以*作为匹配符,例如 news.*匹配所有以 news.开头的频道(news.one、news.global.today 等等)。

    redis> PSUBSCRIBE new.*
    1) "psubscribe"
    2) "new.*"
    3) (integer) 1
    1) "pmessage"
    2) "new.*"      # 消息匹配的模式
    3) "new.one"    # 消息本身的目标频道
    

    注:当订阅客户端同时订阅某种模式和符合该模式的具体某个频道时,那么会接收到发布者推送的信息两次,两次接收的信息格式不同,一个为 message 类型,另一个为 pmessage 类型,消息内容一致。

    取消订阅

    UNSUBSCRIBE命令为取消订阅频道,与订阅频道命令相同,也有对应匹配模式PUNSUBSCRIBE

    如果没有填写指定频道,即一个无参数的UNSUBSCRIBE被调用执行,那么该客户端订阅的所有频道都会被退订。

    由于Redis的订阅操作是阻塞式的,因此一旦客户端订阅了某个频道或模式,就将会一直处于订阅状态直到退出。在SUBSCRIBEPSUBSCRIBEUNSUBSCRIBEPUNSUBSCRIBE命令中,其返回值都包含了该客户端当前订阅的频道和模式的数量,当这个数量变为0时,该客户端会自动退出订阅状态。