原文链接:
发布/订阅(Pub/Sub)
SUBSCRIBE、UNSUBSCRIBE 和 PUBLISH 这三个命令实现了发布/订阅消息模式(引用自维基百科),发送者(发布者)并不是直接发送它们的消息给指定的接收者(订阅者),而是将消息发布到特定的消息通道,并且不需要知道订阅者(如果有的话)的任何信息。订阅者可以订阅一个或多个感兴趣的消息通道,同时也只会收到他们感兴趣通道的信息,而不用去关心是谁发布的。这种发布者与订阅者的解耦,使其具备更强的扩展性并得到一个更加动态的网络拓扑。
例如为了订阅通道foo和bar,客户端可以使用通道名称为参数去调用 SUBSCRIBE 命令:
SUBSCRIBE foo bar
其他客户端发送到消息到这些通道时,消息会由 Redis 推送到所有订阅了这些通道的客户端。
订阅了一个或多个通道的客户端就不应该再使用命令,尽管它还能订阅其他频道或取消订阅其他通道。订阅和取消订阅的执行结果会以消息的形式返回。所以客户端能够解析这互相耦合的消息,其中第一个元素表示消息的类型。订阅了通道的客户端上允许使用的命令有 SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE、PING和QUIT。
推送消息的格式
消息是一条含有三个元素的@array-reply。第一个元素是消息的类型:
- subscribe:意味着我们已经成功订阅了第二个元素所指的通道。第三个参数表示当前已经订阅的通道总数。
- unsubscribe:意味着已经成功的取消了第二个元素所指的通道。第三个参数表示当前订阅的频道总数。当最后一个参数是 0 的时候,就表示不再订阅任何频道,同时客户端也可以使用Redis提供的任何命令,因为此时客户端已经退出发布/订阅状态。
- message:这是某一个客户端使用 PUBLISH 命令后会收到的操作结果信息。第二个元素是信息来源的频道,同时第三个参数是真实消息的内容。
数据库与范围
Pub/Sub 模式与 KEY 空间无关。它与任何层面无关,包括数据库数目。
在 db 10 上进行发布,db 1上的订阅者也会收到信息。
如果你需要覆盖某一些类型,把频道的前缀用一些特定的变量(test,staging,production….)
例如:
SUBSCRIBE first second *3 $9 subscribe $5 first :1 *3 $9 subscribe $6 second :2
此时,从另一个客户端上对 second 频道执行 PUBLISH 命令操作:
PUBLISH second Hello
这就是前面订阅了频道的客户端收到的信息:
*3 $7 message $6 second $5 Hello
现在客户端执行无参的 UNSUBSCRIBE 命令来取消自己订阅的所有频道:
UNSUBSCRIBE *3 $11 unsubscribe $6 second :1 *3 $11 unsubscribe $5 first :0
订阅的模式匹配
Redis 的 Pub/Sub 实现支持模式匹配。客户端可以用 glob 风格的模式去接收频道名称与模式相匹配的所有频道消息。
例如:执行命令PSUBSCRIBE news.*的客户端将后收到所有发送到 news.art.figurative,news.music.jazz 等等频道的信息。所有 glob 风格的模式匹配都是有效的,同时也支持多重通配符。
执行命令PUNSUBSCRIBE news.*的客户端会取消订阅频道名称与 给定模式(news.*) 相匹配的所有频道,而其他已经订阅的频道不会爱影响。模式匹配订阅的信息格式是另一种不同的格式:
消息的类型是 pmessage:表示另一个客户端执行 PUBLISH 命令向频道发送消息,而频道符合当前客户端订阅的模式匹配。第二个元素就是匹配的模式,第三个元素就是模式匹配到的频道名称,最后一个元素就是真正的消息载体。
与系统处理 SUBSCRIBE 和 UNSUBSCRIBE, PSUBSCRIBE 和 PUNSUBSCRIBE 命令一样,发送的消息类型为 psubscribe 和 punsubscribe ,然后使用 subscribe 和 unsubscribe 一样的消息格式。
消息同时匹配模式与订阅的频道
一个客户端可能多次收到同一条消息,如果它订阅的多个模式匹配到了一条发布的消息,或者它订阅的模式与频道匹配到了同一条消息。例如:
SUBSCRIBE foo PSUBSCRIBE f*
在上面的例子中,如果一条消息发送到foo频道,客户端将会收到两条消息。一个是 message类型的消息,一种是pmessage类型的消息。
模式匹配下订阅数的意义
在 subscribe, unsubscribe, psubscribe 和 punsubscribe 等消息类型中,最后一个参数表示仍在订阅的频道数。这个数字实际上就是客户端订阅的频道与模式的总数。
所以当客户端取消订阅所有频道和模式时,也就是这个总数值变为 0 时,客户端将会退出 Pub/Sub 模式。
编程示例
Pieter Noordhuis 提供了一个很好的例子,通过 EventMachine 和 Redis创建了一个多用户高性能的WEB聊天网站。
客户端库实现提示
由于所有的消息都会有一个订阅源。(当消息类型为 message 时,订阅源是一个频道,当消息类型为 pmessage 时,订阅源是一个模式)客户端可以利用一个HASH表将这些订阅源与回调函数绑定起来,这样当一个消息被接收后,能在 O(1) 的时间内将消息交给注册好的回调函数。
原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/114826.html