发布与订阅模型在许多编程语言中都有实现,也就是咱们常常说的设计模式中的一种--观察者模式。在一些应用场合,例如发送方并非以固定频率发送消息,若是接收方频繁去咨询发送方,这种操做无疑是很麻烦而且不友好的。html
举个生活的例子,一个喜欢购买鲜牛奶的人,须要天天在上班的时候/下班的时候都专门去牛奶店购买鲜牛奶,但不必定天天去到那里都恰好有本身喜欢的那一种牛奶,这个时候,这我的跑老远的距离都白费了。但若是这我的去牛奶店一次性订阅了一个月的某种牛奶,那么他就不用担心今天是否能买到鲜牛奶了,只要送奶员把牛奶送到他家楼下的箱子里面就行。python
而订阅发布模型与这个例子有点相似,订阅者只要订阅注册某个频道就能够“高枕无忧”了,当有消息发送过来的时候,会经过订阅的频道接收。优点在于把耦合点独立分离处理,做为发布方和接收方的中介,实现了发布方和接收方的隔离,redis
订阅与发布系统是Redis的一个高级属性,多个客户端能够同时订阅同一个频道,相似广播的机制。所不一样的是,一个客户端能够同时订阅多个频道。编程
样例图:设计模式
Redis订阅发布系统,服务器在背后的工做:服务器
服务器中维护着一个pubsub_channels字典,全部的频道和订阅关系都存储在这里。字典的键为频道的名称,而值为订阅频道的客户端链表。网络
1. 当有新的客户端订阅某个频道时,会发生两种状况中的一种:app
1)若是频道已经存在,则新的客户端会添加到pubsub_channels对应频道的链表末尾编程语言
2)若是频道本来不存在,则会为频道建立一个键,该客户端成为链表的第一个元素ui
2. 当一个客户端退订一个频道的时候:
pubsub_channels对应键的链表会删除该客户端
3. 发送信息
服务器会遍历pubsub_channels中对应键的链表,向每个客户端发送信息
服务器还维护着一个pubsub_patterns链表,链表的pattern属性记录了被订阅的模式,而client属性记录了订阅模式的客户端
1. 当有新的客户端订阅某个模式的时,会进行以下步骤:
1)建立一个链表节点,pattern属性记录订阅的模式,client记录订阅模式的客户端
2)将这个链表节点添加到pubsub_patterns链表中
2. 当一个客户端退订某一个模式的时候:
服务器遍历pubsob_patterns找到对应的pattern同时也是对应该client客户端的节点,将改节点删除
3. 发送信息
服务器遍历pubsub_channels,查找与channels频道相匹配的模式麻将消息发送给订阅了这些模式的客户端。
Redis订阅系统的优点:
1. 当一个客户端向频道发送一个信息,订阅了同一个频道/模式的多个客户端能够同时接收到信息,相似广播的机制。
2. 便于Sentinel哨兵与服务器间的通讯并进行监控
1. 订阅频道
命令格式:
SUSCRIBE channel1 [channel2] [channel3]
例如(同时订阅两个频道):
redis> subscribe local_system remote_system
Reading messages... (press Ctrl-C to quit)
1) "subscribe" # 返回值的类型:显示订阅成功
2) "local_system" # 订阅的频道名字
3)"remote _system "
4) (integer) 2 # 目前已订阅的频道数量
订阅和接收者:
发送者:
注意:客户端一点与某个频道创建链接就不能进行其余操做,一旦客户端退出链接,订阅的频道自动会断开。
2. 订阅模式
PSUBSCRIBE pattern1 [pattern2] [pattern3]
pattern能够用符号*进行模糊匹配,例如:
remo* #匹配以remo开头的模式
*system #匹配以system结尾的模式
例如:
客户端1
客户端2
注意:返回的integer为1是指匹配了一个模式,其实是匹配了两个频道。
发布信息命令:
客户端:
3. 取消订阅:
命令:
1)取消订阅频道
UNSUBSCRIBE channel1 [channel2]
2)取消订阅模式
PUNSUBSCRIBE [pattern [pattern …]]
因为在客户端界面没法实现,这里就不展现了。而在编程过程当中是能够实现的。
关于python中的编程,能够看看这篇文章:
http://www.cnblogs.com/anpengapple/p/7027979.html
4. 发布消息
命令:
PUBLISH channel message
向一个频道发送信息,全部订阅这个频道的客户端都会接收到信息
5. 查看已有的频道
命令:
PUBSUB subcommand [argument [argument ...]]
subcommand子命令:
1)PUBSUB CHANNELS [pattern]
列出当前的活跃频道
若是给定pattern参数,则会返回服务器当前被订阅的频道中与pattern模式相匹配的频道
2)PUBSUB NUMSUB [channel-1 … channel-N]
返回给定频道的订阅者数量, 订阅模式的客户端不计算在内
由于有一个是匹配模式,因此返回的interger值为1
3)PUBSUB NUMPAT
返回订阅模式的数量
Sentinel哨兵中的应用:
Sentinel服务器与Master服务器/Slave服务器之间的订阅发布系统是Sentinl监控过程的一个重要环节,经过订阅发布系统达到监控服务器状态的做用。其运行原理与上面的客户端服务器之间的订阅机制无太大区别,都是基于网络链接的数据传输。Sentinel之间的通讯也是经过Sentinel与服务武器间的这个订阅发布系统实现的,一个Sentinel经过服务器的频道发送信息,其余Sentinel就会接收到。
参考文章:
http://www.cnblogs.com/anpengapple/p/7027979.html
《redis设计与实现》