发布/订阅
SUBSCRIBE,UNSUBSCRIBE和PUBLISH 实现了发布/订阅消息传递范例,其中(引用维基百科)发件人(发布者)未被编程为将其消息发送给特定接收者(订阅者)。相反,发布的消息被表征为信道,而不知道可能存在什么(如果有的话)订户。订阅者表达对一个或多个频道的兴趣,并且仅接收感兴趣的消息,而不知道有哪些(如果有的话)发布者。发布者和订阅者的这种分离可以允许更大的可扩展性和更动态的网络拓扑。
例如,为了订阅频道foo
和bar
,客户端发出提供频道名称的SUBSCRIBE:
SUBSCRIBE foo bar
其他客户端发送到这些频道的消息将由Redis推送到所有订阅的客户端。
订阅一个或多个频道的客户端不应发出命令,但是它可以订阅和取消订阅其他频道。对订阅和取消订阅操作的回复以消息的形式发送,以便客户端可以只读取连贯的消息流,其中第一个元素指示消息的类型。订阅客户端上下文中允许的命令是SUBSCRIBE,PSUBSCRIBE,UNSUBSCRIBE,PUNSUBSCRIBE, PING和QUIT。
请注意,redis-cli
在订阅模式下不会接受任何命令,并且只能退出模式Ctrl-C
。
推送消息的格式
消息是具有三个元素的Array回复。
第一个元素是消息的类型:
-
subscribe
:表示我们成功订阅了作为回复中第二个元素的通道。第三个参数表示我们当前订阅的频道数。 -
unsubscribe
:表示我们成功取消订阅作为回复中第二个元素的频道。第三个参数表示我们当前订阅的频道数。当最后一个参数为零时,我们不再订阅任何通道,并且客户端可以发出任何类型的Redis命令,因为我们在Pub / Sub状态之外。 -
message
:它是由另一个客户端发出的PUBLISH命令收到的消息。第二个元素是原始通道的名称,第三个参数是实际的消息有效负载。
数据库和范围
Pub/Sub与key空间无关。它被认为不会在任何级别上干扰它,包括数据库号。
数据库1上的订阅者将听到db 10上的发布。
如果您需要某种范围,请在通道前加上环境名称(测试,登台,生产......)。
示例
SUBSCRIBE first second
*3
$9
subscribe
$5
first
:1
*3
$9
subscribe
$6
second
:2
此时,我们从另一个客户端发出针对名为的通道的PUBLISH操作second
:
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.*
然后将取消订阅该模式的客户端。此通话不会影响其他订阅。
由于模式匹配而收到的消息以不同的格式发送:
- 消息的类型是
pmessage
:它是由另一个客户端发出的PUBLISH命令接收的消息,匹配模式匹配订阅。第二个元素是原始模式匹配,第三个元素是原始通道的名称,最后一个元素是实际消息有效负载。
类似于SUBSCRIBE和UNSUBSCRIBE,PSUBSCRIBE和 PUNSUBSCRIBE命令由系统发送类型的消息确认psubscribe
和punsubscribe
使用相同的格式 subscribe
和unsubscribe
消息格式。
匹配模式和频道订阅的消息
如果客户端订阅了与已发布消息匹配的多个模式,或者如果订阅了与该消息匹配的模式和信道,则客户端可以多次接收单个消息。如下例所示:
SUBSCRIBE foo
PSUBSCRIBE f*
在上面的示例中,如果将消息发送到通道foo
,则客户端将收到两条消息:类型message
之一和类型之一 pmessage
。
与模式匹配的订阅计数的含义
在subscribe
和unsubscribe
,psubscribe
以及punsubscribe
消息类型中,最后一个参数是仍处于活动状态的订阅计数。此数字实际上是客户端仍订阅的频道和模式的总数。因此,只有当此计数从所有通道和模式取消订阅后降至零时,客户端才会退出发布/订阅状态。
客户端库实现提示
因为收到的所有消息都包含导致消息传递的原始订阅(消息类型为通道,pmessage类型为原始模式)客户端库可能会将原始订阅绑定到回调(可以是匿名函数,块,函数指针),使用哈希表。
当收到消息时,可以进行O(1)查找,以便将消息传递给已注册的回调。