# Redis 发布/订阅

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

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

例如,为了订阅频道foobar客户端发出一个 SUBSCRIBE 提供频道名称的请求:

SUBSCRIBE foo bar

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

订阅一个或多个频道的客户端不应发出命令,尽管它可以订阅和取消订阅其他频道。订阅和取消订阅操作的回复以消息的形式发送,以便客户端可以读取连贯的消息流,其中第一个元素指示消息的类型。订阅客户端上下文中允许的命令是 SUBSCRIBE, SSUBSCRIBE, SUNSUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE, PUNSUBSCRIBE, PING, RESET, 和 QUIT.

请注意,redis-cli一旦在订阅模式下将不会接受任何命令,并且只能使用 退出模式Ctrl-C

# 推送消息的格式

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

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

  • subscribe: 表示我们成功订阅了作为回复中第二个元素给出的频道。第三个参数表示我们当前订阅的频道数量。
  • unsubscribe: 表示我们已成功取消订阅作为回复中第二个元素给出的频道。第三个参数表示我们当前订阅的频道数量。当最后一个参数为零时,我们不再订阅任何频道,并且客户端可以发出任何类型的 Redis 命令,因为我们处于 Pub/Sub 状态之外。
  • message:它是由于 PUBLISH 另一个客户端发出的命令而收到的消息。第二个元素是原始通道的名称,第三个参数是实际的消息负载。

# 数据库和范围

Pub/Sub 与密钥空间无关。它不会在任何级别上干扰它,包括数据库编号。

在 db 10 上发布,将由 db 1 上的订阅者听到。

如果您需要某种范围,请在通道前加上环境名称(测试、登台、生产......)。

# 有线协议示例

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.figurativenews.music.jazz等等。所有 glob 样式的模式都是有效的,因此支持多个通配符。

PUNSUBSCRIBE news.*

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

由于模式匹配而收到的消息以不同的格式发送:

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

SUBSCRIBE 与and类似 UNSUBSCRIBEPSUBSCRIBEPUNSUBSCRIBE 命令由系统确认发送类型的消息psubscribe 并使用与and消息格式 punsubscribe 相同的 格式。subscribeunsubscribe

# 匹配模式和频道订阅的消息

如果客户端订阅了与已发布消息匹配的多个模式,或者订阅了与消息匹配的模式和通道,则客户端可能会多次收到一条消息。就像下面的例子:

SUBSCRIBE foo
PSUBSCRIBE f*

在上面的例子中,如果一条消息被发送到 channel foo,客户端将收到两条消息:一条是 type message,一条是 type pmessage

# 订阅计数与模式匹配的含义

subscribeunsubscribe和消息 类型中psubscribepunsubscribe 最后一个参数是仍处于活动状态的订阅数。这个数字实际上是客户端仍然订阅的频道和模式的总数。因此,仅当由于取消订阅所有频道和模式而导致该计数降至零时,客户端才会退出 Pub/Sub 状态。

# 分片发布/订阅

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

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

# 编程示例

Pieter Noordhuis 提供了一个很好的示例,使用 EventMachine 和 Redis 创建多用户高性能网络聊天。

# 客户端库实现提示

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

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

# 反馈

如果您在此页面上发现问题,或有改进建议,请提交请求以合并或打开存储库中的问题。

Last Updated: 4/18/2023, 8:45:33 AM