zoukankan      html  css  js  c++  java
  • redis 订阅与发布

    • PUBLISH,SUBSCRIBE,等命令实现订阅与发布
      • 订阅/发布到频道
      • 订阅/发布到模式
     
    频道的订阅与信息发送

     
    订阅subscribe,可以让客户端订阅任意数量的频道,
    每当有新信息发送到被订阅的频道时,信息就会被发送给所有订阅指定频道的客户端:
     
     
    当有新消息通过publish命令发送给频道channel1时,这个消息就会被发送给订阅它的三个客户端:
     
    订阅频道
    每个 Redis 服务器进程都维持着一个表示服务器状态的 redis.h/redisServer 结构,结构的
    pubsub_channels 属性是一个字典,这个字典就用于保存订阅频道的信息:
    struct redisServer {
    // ...
    dict *pubsub_channels;
    // ...
    };
    

      

    其中字典的键为正在被订阅的频道,而字典的值则是一个链表,链表中保存了所有订阅这个频道的客户端。
    例如:
     
    当客户端调用subscribe命令时,程序将客户端和要订阅的频道在pubsub_channels字典中关联起来。
    举个例子,如果客户端 client10086 执行命令 SUBSCRIBE channel1 channel2 channel3 ,
    那么前面展示的 pubsub_channels 将变成下面这个样子:
     
    发送信息到频道
    当调用 PUBLISH channel message 命令,程序首先根据 channel 定位到字典的键,然后将信息发
    送给字典值链表中的所有客户端。
     
    如果某个客户端执行命令
    PUBLISH channel1 "hello moto" ,上图中那么 client2 、 client5 ,client1,client10086 4个客户端都将接收到 "hello moto"
     
    退订频道
    UNSUBSCRIBE 命令可以退订指定的频道, 它从pubsub_channels 字典的给定频道(键)中,删除关于当前客户端的信息,这样被退订频道的信息就不会再发送给这个客户端。
     
    模式的订阅与信息发送

    当使用 PUBLISH 命令发送信息到某个频道时,不仅所有订阅该频道的客户端会收到信息,如
    果有某个/某些模式和这个频道匹配的话,那么所有订阅这个/这些频道的客户端也同样会收到
    信息。
     
    带频道和模式的例子, 其中 tweet.shop.* 模式匹配了 tweet.shop.kindle
    频道和 tweet.shop.ipad 频道,并且有不同的客户端分别订阅它们三个:
     
    当有信息发送到 tweet.shop.kindle 频道时,信息除了发送给 clientX 和 clientY 之外,还
    会发送给订阅 tweet.shop.* 模式的 client123 和 client256 :
     
    订阅模式
    redisServer.pubsub_patterns 属性是一个链表,链表中保存着所有和模式相关的信息:
     
    struct redisServer {
         // ...
         list *pubsub_patterns;
         // ...
    };
    

      

    链表中的每个节点都包含一个 redis.h/pubsubPattern 结构:
    typedef struct pubsubPattern {
         redisClient *client;
         robj *pattern;
    } pubsubPattern;
     
    

      

    client 属性保存着订阅模式的客户端,而 pattern 属性则保存着被订阅的模式。
    每当调用 PSUBSCRIBE 命令订阅一个模式时,程序就创建一个包含客户端信息和被订阅模式的
    pubsubPattern 结构,并将该结构添加到 redisServer.pubsub_patterns 链表中。
     
     
    如果这时客户端 client10086 执行 PSUBSCRIBE broadcast.list.* ,那么 pubsub_patterns
    链表将被更新成这样:
    通过遍历整个 pubsub_patterns 链表,程序可以检查所有正在被订阅的模式,以及订阅这些模式的客户端。
     
     
    发送信息到模式
    发送信息到模式的工作也是由 PUBLISH 命令进行的,在前面讲解频道的时候,我们给出了这
    样一段伪代码,说它定义了 PUBLISH 命令的行为:
    def PUBLISH(channel, message):
     
         # 遍历所有订阅频道 channel 的客户端
         for client in server.pubsub_channels[channel]:
     
              # 将信息发送给它们
              send_message(client, message)
     
         # 取出所有模式,以及订阅模式的客户端
         for pattern, client in server.pubsub_patterns:
     
              # 如果 channel 和模式匹配
              if match(channel, pattern):
                  
                   # 那么也将信息发给订阅这个模式的客户端
                   send_message(client, message)
     
     
    

      

    退订模式
    使用 PUNSUBSCRIBE 命令可以退订指定的模式,这个命令执行的是订阅模式的反操作:程序
    会删除 redisServer.pubsub_patterns 链表中,所有和被退订模式相关联的 pubsubPattern
    结构,这样客户端就不会再收到和模式相匹配的频道发来的信息。
     
    小结
    • 订阅信息由服务器进程维持的 redisServer.pubsub_channels 字典保存,
      • 字典的键为被订阅的频道,字典的值为订阅频道的所有客户端。
    • 当有新消息发送到频道时,程序遍历频道(键)所对应的(值)所有客户端,
      • 然后将消息发送到所有订阅频道的客户端上。
    • 订阅模式的信息由服务器进程维持的 redisServer.pubsub_patterns 链表保存,
      • 链表的每个节点都保存着一个pubsubPattern结构,结构中保存着被订阅的模式,
      • 以及订阅该模式的客户端。程序通过遍历链表来查找某个频道是否和某个模式匹配。
    • 当有新消息发送到频道时,除了订阅频道的客户端会收到消息之外,
      • 所有订阅了匹配频、道的模式的客户端,也同样会收到消息。
    • 退订频道和退订模式分别是订阅频道和订阅模式的反操作。
  • 相关阅读:
    【JOI2017春季合宿】Port Facility
    LOJ504「LibreOJ β Round」ZQC 的手办
    UOJ37. 【清华集训2014】主旋律
    CF1012F Passports
    AT2370 Piling Up
    CF908G New Year and Original Order
    CF643E Bear and Destroying Subtrees
    CF183D T-shirt
    「JOISC 2016 Day 3」回转寿司
    「LibreOJ β Round #2」计算几何瞎暴力
  • 原文地址:https://www.cnblogs.com/Aiapple/p/7255609.html
Copyright © 2011-2022 走看看