Redis Pub/Sub

内容纲要

如何在Redis中使用pub/sub通道

SUBSCRIBE、UNSUBSCRIBE和PUBLISH实现了PUBLISH / SUBSCRIBE消息传递范式,其中(引用维基百科)发送者(发布者)没有被编程为将消息发送给特定的接收者(订阅者)。相反,发布的消息被划分为通道,而不知道可能有哪些订阅者(如果有的话)。订阅者表示对一个或多个频道感兴趣,并且只接收感兴趣的消息,而不知道有什么(如果有的话)发布者。发布者和订阅者的这种解耦可以实现更大的可伸缩性和更动态的网络拓扑。

例如,为了订阅通道foo和bar,客户端发出一个subscribe,提供通道的名称:

SUBSCRIBE foo bar

其他客户端发送到这些频道的消息将被Redis推送到所有订阅的客户端。

订阅了一个或多个通道的客户端不应该发出命令,尽管它可以向其他通道订阅或取消订阅。订阅和取消订阅操作的回复以消息的形式发送,这样客户机就可以读取一致的消息流,其中第一个元素表示消息的类型。在订阅的客户端上下文中允许的命令有SUBSCRIBE、SSUBSCRIBE、SUNSUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE、PUNSUBSCRIBE、PING、RESET和QUIT。

请注意,redis-cli在订阅模式下不接受任何命令,只能使用Ctrl-C退出该模式。

推送消息的格式

消息是一个包含三个元素的数组-回复。

第一个元素是消息的类型:

  • 订阅:意味着我们成功订阅了回复中第二个元素给出的频道。第三个参数表示当前订阅的频道数量。

  • 取消订阅:意味着我们成功地从回复中第二个元素给出的通道取消订阅。第三个参数表示当前订阅的频道数量。当最后一个参数为0时,我们不再订阅任何通道,客户端可以发出任何类型的Redis命令,因为我们不在发布/订阅状态。

  • message:它是另一个客户端发出PUBLISH命令后收到的消息。第二个元素是原始通道的名称,第三个参数是实际的消息有效负载。

数据库 & 范围

Pub/Sub与键空间没有关系。它不会在任何层面上干扰它,包括数据库号码。

在db 10上发布,用户将在db 1上听到。

如果需要某种作用域,可以在通道前面加上环境的名称(测试、登台、生产……)。

有线协议示例

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发布/订阅实现支持模式匹配。客户端可以订阅全局样式模式,以便接收发送到与给定模式匹配的通道名的所有消息。

例如:

PSUBSCRIBE news.*

将接收所有发送到news.art频道的消息。比喻,news.music。爵士等。所有全局样式的模式都是有效的,因此支持多个通配符。

PUNSUBSCRIBE news.*

然后将客户端从该模式中取消订阅。此调用不会影响其他订阅。

作为模式匹配结果接收的消息以不同的格式发送:

  • 消息的类型是pmessage:它是另一个客户端发出的PUBLISH命令所接收到的消息,匹配模式匹配订阅。第二个元素是匹配的原始模式,第三个元素是原始通道的名称,最后一个元素是实际的消息有效负载。

与SUBSCRIBE和UNSUBSCRIBE类似,系统发送PSUBSCRIBE和PUNSUBSCRIBE类型的消息时,使用与订阅和UNSUBSCRIBE消息格式相同的格式确认PSUBSCRIBE和PUNSUBSCRIBE命令。

同时匹配模式和通道订阅的消息

如果客户端订阅了与已发布消息匹配的多个模式,或者同时订阅了与消息匹配的模式和通道,则客户端可能会多次接收单个消息。如下面的例子所示:

SUBSCRIBE foo
PSUBSCRIBE f*

在上面的例子中,如果一个消息被发送到通道foo,客户端将收到两个消息:一个是message类型的消息,一个是pmessage类型的消息。

订阅计数与模式匹配的意义

在subscribe、unsubscribe、psubscribe和punsubscribe消息类型中,最后一个参数是仍然活动的订阅数。这个数字实际上是客户端仍然订阅的通道和模式的总数。因此,只有当由于取消订阅所有频道和模式而导致该计数降为零时,客户机才会退出发布/订阅状态。

分片Pub / Sub

从7.0开始,引入了分片Pub/Sub,其中将分片通道分配给插槽,使用与分配密钥到插槽相同的算法。分片消息必须发送到拥有分片通道散列到的槽的节点。集群确保发布的shard消息被转发到shard中的所有节点,因此客户端可以通过连接负责插槽的主节点或其任何副本来订阅shard通道。采用SSUBSCRIBE、SUNSUBSCRIBE和SPUBLISH实现分片发布/订阅。

分片发布/订阅有助于扩展集群模式下发布/订阅的使用。它将消息的传播限制在集群的碎片内。因此,与全局Pub/Sub相比,通过集群总线的数据量是有限的,在全局Pub/Sub中,每个消息都传播到集群中的每个节点。这允许用户通过添加更多碎片来水平扩展发布/订阅的使用。

编程示例

Pieter Noordhuis提供了一个使用EventMachine和Redis创建多用户高性能web聊天的好例子。

客户端库实现提示

因为接收到的所有消息都包含导致消息传递的原始订阅(对于消息类型是通道,对于pmessage类型是原始模式),客户端库可以使用哈希表将原始订阅绑定到回调(可以是匿名函数、块、函数指针)。

当接收到消息时,可以执行O(1)查找,以便将消息传递给已注册的回调。

Leave a Comment

您的电子邮箱地址不会被公开。 必填项已用*标注

close
arrow_upward