【0】发布订阅架构图

  

    客户端订阅某个频道,让后有人在频道上发布信息,频道就分发给所有的客户端。

  举个例子:就和微信公众号一样,文章作者者把文章发到微信公众号上,微信公众号平台把文章推送到所有的订阅用户上。

  应用场景:

    (1)在博客网站中,有100个粉丝订阅了你,当你发布新文章时,就可以推送消息给他们。

    (2)微信公众号模式

    (3)类似于开发设计模式中的 观察者模式

【1】命令

  【1.1】订阅频道

    subscribe channel1 channel2.....  订阅一个或多个指定的频道   subscribe cctv1 cctv2

    psubscribe pattern1 parttern2....   订阅一个或多个符合特定模式的频道  psubscribe cctv*

  【1.2】发布频道信息

    publish channel1 message1    将 message1 发送到指定的 channel1 频道  publish cctv1 hello

    publish numsub channel:channel1    查看 channel1频道中有多少订阅

  【1.3】退订频道  

    unsubscribe channel1 channel2.....  退订一个或多个指定的频道 subscribe cctv1 cctv2

    punsubscribe pattern1 pattern2.....   退订一个或多个特定模式的频道 publish cctv*

【2】实操演示

   【2.1】订阅频道 subscribe channel1

    

  【2.2】发布频道信息 publish channel messages1

    如果当前频道没有任何订阅者,下图中第2行会显示0,否则有n个订阅者这里就会显示n。

    

  【2.3】查看消息

    客户端1:发布消息

      

    客户端2:接受消息

      

  【2.4】特定模式的订阅与消息查收

    命令操作顺序

    (1)psubscribe cctv*(session1)

    (2)publish cctv1 'hello,cctv1'(session2)

    (3)publish cctv2 'hello,cctv2'(session2)

    且,其接受消息的 message 字段显示成了 pmessage

    session1

      

    session2

      

【3】基本运作原理

每个Redis 服务器进程都维持着一个表示服务器状态的 redis.h/redisServer结构, 结构的pubsub_channels 属性是一个字典, 这个字典就用于保存订阅频道的信息:

struct redisServer {
// ...
dict *pubsub_channels;
// ...
};

其中,字典的键为正在被订阅的频道, 而字典的值则是一个链表, 链表中保存了所有订阅这个频道的客户端。
比如说,在下图展示的这个pubsub_channels示例中,client1 、 client2 和 client3 就订阅了 channel1 , 而client3也同时订阅了channel2。
当客户端调用SUBSCRIBE命令时, 程序就将客户端和要订阅的频道在pubsub_channels字典中关联起来。

  

SUBSCRIBE 命令的行为可以用伪代码表示如下:

def SUBSCRIBE(client, channels):

    // 遍历所有输入频道
for channel in channels: // 将客户端添加到链表的末尾
redisServer.pubsub_channels[channel].append(client)

  通过pubsub_channels字典, 程序只要检查某个频道是否为字典的键, 就可以知道该频道是否正在被客户端订阅; 只要取出某个键的值, 就可以得到所有订阅该频道的客户端的信息。

  了解了pubsub_channels字典的结构之后, 解释PUBLISH命令的实现就非常简单了: 当调用PUBLISH channel message命令, 程序首先根据channel定位到字典的键, 然后将信息发送给字典值链表中的所有客户端。

订阅模式

  redis的发布订阅不仅仅提供简单的订阅频道,还提供模式匹配订阅。模式订阅使用命令PSUBSCRIBE实现。

  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链表中。
作为例子,下图展示了一个包含两个模式的 pubsub_patterns 链表, 其中 client123 和 client256 都正在订阅 tweet.shop.* 模式:

通过遍历整个pubsub_patterns链表,程序可以检查所有正在被订阅的模式,以及订阅这些模式的客户端。

  当执行PUBLISH进行命令向channel命令发送消息时,PUBLISH除了将message 发送到所有订阅channel的客户端之外, 它还会将channel和pubsub_patterns中的模式进行对比,。

  如果channel和某个模式匹配的话, 那么也将message 发送到订阅那个模式的客户端,例如一个客户端订阅了aa.bb.*频道,那么他会收到来自所有aa.bb开头的所有频道消息。

参考:https://www.cnblogs.com/wdliu/p/9360286.html

最新文章

  1. Java中的进程和线程
  2. AngularJS 脏检查深入分析
  3. Microsoft.Web.Redis.RedisSessionStateProvider
  4. Linux CAT与ECHO命令详解 <<EOF EOF
  5. 【转】从RGB色转为灰度色算法
  6. PostGreSQL 分页
  7. Thrift——初学
  8. 一些不错的英文歌曲MV,留个存档!
  9. Redis实战
  10. HDU 1059 Dividing(多重背包)
  11. Html笔记(二)字体
  12. 简约的返回顶部效果(jQuery)
  13. 201521123091 《Java程序设计》第9周学习总结
  14. Windows Server 2016-图形化备份域控制器
  15. C++中将构造函数或析构函数定义为private
  16. BZOJ5177 : [Jsoi2013]贪心的导游
  17. stl string的erase方法
  18. TensorFlow入门,基本介绍,基本概念,计算图,pip安装,helloworld示例,实现简单的神经网络
  19. error C4996: Function call with parameters that may be unsafe – this call relies on the caller to ch
  20. C#控件之:进度条(ProgressBar)

热门文章

  1. AGC032F One Third
  2. jQuery的入口函数
  3. MIME协议(二)
  4. [JZOJ6345]:ZYB建围墙(数学+构造)
  5. Linux设备驱动程序 之 原子操作
  6. C# 7 .NET / CLR / Visual Studio version requirements
  7. centos7 开启80端口
  8. LC 738. Monotone Increasing Digits
  9. 演示Java如何调用Mysql的过程和函数
  10. Ubuntu vmware补丁