原文 https://redis.io/topics/pubsub


【发布/订阅】

SUBSCRIBE、UNSUBSCRIBE 和 PUBLISH 命令实现“发布/订阅消息范式”,即发送者(发布者)不设定发送消息给指定的接收者(订阅者),而是将发布的消息分类到各频道中,不必知道订阅者是谁或是否有订阅者,订阅者表示对一个或多个频道感兴趣,只管接收这些频道的消息即可,不必知道发布者是谁或在哪儿,如此,解除发布者和订阅者之间的耦合关系,能允许更好的扩展性和更动态的网络拓扑

例如,要订阅foo和bar频道,客户端发起带频道名的SUBSCRIBE即可:
subscribe foo bar

消息由另一个客户端发送到foo和bar频道后,Redis将推送这些消息到所有已订阅的客户端,这些已订阅的客户端无需发起任何命令,除非它要订阅其他频道或退订已有频道,订阅和退订操作的应答以消息形式发送,客户端只需读取一连串消息,其第一个元素表示消息的类型,一个已订阅的客户端允许执行的命令有 SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE、PING 和 QUIT


【推送消息的格式】

每个消息都是一个由三项元素组成的数组,第一个元素表示消息类型,有以下三种:
- subscribe,订阅,意为成功订阅了第二项元素所指的频道,第三项元素则表示该客户端当前订阅的频道数量
- unsubscribe,退订,意为成功退订了第二项元素所指的频道,第三项元素依然表示该客户端当前订阅的频道数量,当该项元素为0时表示不再订阅任何频道,客户端退出“发布/订阅”状态,可以发起任何Redis命令
- message,消息,意为这是一个接收到的消息,来自其他执行PUBLISH命令的客户端,第二项元素是频道名,第三项元素则是实际的消息内容


【数据库和范围】

注:这段是我在理解了原文意思后用自己的话写的,因为原文描述的太不清楚了

发布/订阅不关联到键空间(key space),频道名在所有DB上都是可见的,即全局跨DB的,在DB10上发布的消息,可以在DB1上订阅到,即,在DB1上可以订阅到在DB10上发布的消息,为了更有效的区分不同频道,可以在频道命名上加以规范,例如在频道名上加前后缀,以区分环境(test/staging/production)或不同应用


【协议演示】

在客户端A发起订阅:
SUBSCRIBE first second
*3
$9
subscribe
$5
first
:1
*3
$9
subscribe
$6
second
:2

此时,在另一个客户端B发起PUBLISH命令对频道second的发布消息:
> publish second Hello

客户端A会接收到:
*3
$7
message
$6
second
$5
Hello

现在客户端A使用不带任何参数的UNSUBSCRIBE命令退订所有频道:
UNSUBSCRIBE
*3
$11
unsubscribe
$6
second
:1
*3
$11
unsubscribe
$5
first
:0


【模式匹配订阅】

Redis的发布/订阅实现了对频道名模式(pattern)匹配的支持,客户端可以订阅名字匹配给定模式的所有频道,并接收到这些频道的所有消息,所有模式匹配都有效,多通配符也能支持

例如:
psubscribe news.*
将接收到所有发送给news.art、news.music等以news.开头的频道的消息

再如:
punsubscribe news.*
将退订匹配该模式的所有频道,其他频道的订阅不会受到影响

模式匹配的结果会以不同格式被客户端当信息接收到:
- 消息类型是 pmessage,接收到的消息是由其他客户端发起PUBLISH命令发送且匹配当前客户端订阅模式的消息,第二项元素是匹配的模式,第三项元素是该模式匹配到的频道名,最后项元素是真实的消息内容


【既有模式匹配又有频道订阅】

如果一个客户端订阅了多个模式匹配同一个消息发布者,或订阅的频道与匹配到的模式重合,将会多次接收到同一条消息

例如:
SUBSCRIBE foo
PSUBSCRIBE f*
在这个例子中,如果一个消息发送给频道foo,客户端将收到二次,一次是来自foo订阅的message类型,一次是来自f*模式匹配订阅的pmessage类型


【订阅个数的意思】

在subscribe、unsubscribe、psubscribe和punsubscribe的应答消息数组中,最后项元素都是该客户端当前仍有的订阅数量,该数量是订阅的频道数和模式数之和,当退订了所有的频道和模式后该数量减到0,客户端将退出发布/订阅状态,又可以发送命令给Redis了


10-17 03:11