本文基于Redis 6.0.9版本,前提至少 Redis 3.0或更高版本。
目录
1.相关命令
2.Pub/Sub
SUBSCRIBE, UNSUBSCRIBE, PUBLISH 实现了“发布/订阅”消息传递范例,其中(引用Wikipedia)发送者(发布者)没有被编程为将其消息发送给特定的接收者(订阅者)。 而是,将发布的消息定性为通道,而不知道可能有哪些(如果有)订阅者。 订阅者对一个或多个渠道表示兴趣,并且仅接收感兴趣的消息,而不知道那里有哪些发布者。 发布者和订阅者之间的这种解耦可以实现更大的可伸缩性和更动态的网络拓扑。
例如,为了订阅foo和bar频道,客户端发出SUBSCRIBE来提供频道的名称:
SUBSCRIBE foo bar
其他客户端发送到这些频道的消息将由Redis推送到所有订阅的客户端。
订阅了一个或多个频道的客户端尽管可以订阅和取消订阅其他频道,但不应发出命令。对订阅和取消订阅操作的回复以消息的形式发送,以便客户端可以读取连贯的消息流,其中第一个元素表示消息的类型。在订阅的客户端的上下文中允许的命令是SUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE, PUNSUBSCRIBE, PING, QUIT。
请注意,在订阅模式下redis-cli将不接受任何命令,并且只能使用Ctrl-C退出该模式。
2.1.推送消息的格式
消息是具有三个元素的数组回复。
第一个元素是消息的种类:
- subscription:表示我们已成功订阅了作为回复中第二个元素的频道。 第三个参数表示我们当前订阅的频道数。
- unsubscribe:表示我们已成功退出了作为回复中第二个元素的频道。 第三个参数表示我们当前订阅的频道数。 当最后一个参数为零时,我们将不再订阅任何频道,并且由于我们不在发布/订阅状态,因此客户端可以发出任何类型的Redis命令。
- message:这是另一个客户端发出的PUBLISH命令的结果。 第二个元素是始发通道的名称,第三个参数是实际的消息有效负载。
2.2.数据库和作用域
Pub/Sub与密钥空间无关。 使其在任何级别(包括数据库编号)都不会受到干扰。
在db 10上发布,将由db 1上的订阅者听到。
如果您需要某种范围,请在通道之前添加环境名称(test, staging, production等)。
2.3.有线协议(Wire protocol)示例
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
2.4.模式匹配(Pattern-matching)订阅
Redis Pub/Sub 实现支持模式匹配。 客户端可以订阅glob样式的模式,以便接收发送到与给定模式匹配的频道名称的所有消息。
例如:
PSUBSCRIBE news.*
将接收发送到通道news.art.figurative
, news.music.jazz
等的所有消息。所有glob-style的模式均有效,因此支持多个通配符。
PUNSUBSCRIBE news.*
然后将取消订阅(unsubscribe)该模式的客户。 此呼叫不会影响其他订阅(subscriptions)。
由于模式匹配而收到的消息以不同的格式发送:
- 消息的类型是pmessage: 它是收到消息,该消息是由另一个客户端发布并且匹配pattern-matching订阅(subscription)的PUBLISH命令。 第二个元素是匹配的原始模式,第三个元素是始发通道的名称,最后一个元素是实际的消息有效负载。
与SUBSCRIBE和 UNSUBSCRIBE相似,系统会使用与subscribe
和unsubscribe
消息格式相同的格式发送psubscribe和punsubscribe类型的消息来确认PSUBSCRIBE 和 PUNSUBSCRIBE命令。
2.5.与模式和频道订阅均匹配的消息
如果客户端订阅了与已发布消息匹配的多个模式,或者订阅了与消息匹配的模式和通道,则客户端可能会多次收到一条消息。 如以下示例所示:
SUBSCRIBE foo
PSUBSCRIBE f*
在上面的示例中,如果将一条消息发送到foo通道,则客户端将收到两条消息:一条消息为message类型,另一条消息为pmessage类型。
2.6.模式匹配的订阅计数的含义
在subscribe
, unsubscribe
, psubscribe
, punsubscribe
消息类型中,最后一个参数是仍处于活动状态的订阅数。 该数字实际上是客户端仍订阅的频道和模式的总数。 因此,仅当由于取消订阅(unsubscribing )所有通道和模式而使计数降至零时,客户端才会退出发布/订阅状态。
2.7.编程实例
Pieter Noordhuis提供了一个使用EventMachine和Redis创建多用户高性能Web聊天的好例子。
2.8.客户端库实现hints
由于收到的所有消息都包含导致消息传递的原始订阅(subscription )(在消息类型中是通道(channel),在pmessage类型中是原始模式(original pattern)),客户端库可以将原始订阅绑定到回调(可以是匿名函数, 块,函数指针),使用哈希表。
收到消息后,可以进行O(1)查找,以将消息传递给已注册的回调。