Redis 进阶 -- 发布与订阅

Posted CodeJiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis 进阶 -- 发布与订阅相关的知识,希望对你有一定的参考价值。

文章目录

1. 发布与订阅

Redis的发布与订阅功能可以让客户端通过广播方式,将消息(message)同时发送给可能存在的多个客户端,并且发送消息的客户端不需要知道接收消息的客户端的具体信息。换句话说,发布消息的客户端与接收消息的客户端两者之间没有直接联系。

在Redis中,客户端可以通过订阅特定的频道(channel)来接收发送至该频道的消息,我们把这些订阅频道的客户端称为订阅者(subscriber)。一个频道可以有任意多个订阅者,而一个订阅者也可以同时订阅任意多个频道。除此之外,客户端还可以通过向频道发送消息的方式,将消息发送给频道的所有订阅者,我们把这些发送消息的客户端称为发送者(publisher)

示例:

下图展示了一个订阅频道的例子,在这个例子中,客户端client-2、client-3和client-4都订阅了频道"news.it"。

如果这时客户端client-1向频道"news.it"发送消息"hello world",那么client-2、client-3和client-4都将接收到这条消息:

除了订阅频道之外,客户端还可以通过订阅模式(pattern)来接收消息:每当发布者向某个频道发送消息的时候,不仅频道的订阅者会收到消息,与频道匹配的所有模式的订阅者也会收到消息。

下图展示了一个订阅模式的例子,在这个例子中,频道"news.it"和频道"news.sport"都有它们各自的订阅者,而客户端client-7、client-8和client-9则订阅了模式"news.*“,这个模式与"news.it"频道以及"news.sport"频道相匹配。

这时,如果客户端client-1向"news.it"频道发送消息"hello it”,那么不仅"news.it"频道的订阅者client-2、client-3和client-4会收到消息,"news.*“模式的订阅者client-7、client-8和client-9也会收到消息,如图所示。

与此类似,如果客户端client-1向"news.sport"频道发送消息"hello sport”,那么不仅"news.sport"频道的订阅者client-5和client-6会收到消息,"news.*"模式的订阅者client-7、client-8和client-9也会收到消息,如图所示。


1.1 PUBLISH:向频道发送消息

用户可以通过执行PUBLISH命令,将一条消息发送至给定频道。

语法:


PUBLISH命令会返回接收到消息的客户端数量作为返回值。

示例:

如果我们想要向频道"news.it"发送消息"hello world",那么只需要执行以下命令即可:

命令返回3表示有3个客户端接收到了这条消息。


1.2 SUBSCRIBE:订阅频道

用户可以通过执行SUBSCRIBE命令,让客户端订阅给定的一个或多个频道。

语法:


SUBSCRIBE命令在每次成功订阅一个频道之后,都会向执行命令的客户端返回一条订阅消息,消息包含了被成功订阅的频道以及客户端目前已订阅的频道数量。

示例:

如果我们想要订阅"news.it"频道,那么可以执行以下命令:

SUBSCRIBE命令在订阅"news.it"频道之后向客户端返回了一条订阅消息:

  • 消息的第一个元素是"subscribe",它表示这条消息是由SUBSCRIBE命令引发的订阅消息而不是普通客户端发送的频道消息。
  • 消息的第二个元素记录了被订阅频道的名字"news.it"。
  • 消息的最后一个元素是数字1,这表示客户端目前只订阅了一个频道。

如果我们使用SUBSCRIBE命令同时订阅多个频道,那么命令将返回多条订阅消息,就像这样:


1.2.1 接收频道消息

当客户端成为频道的订阅者之后,就会接收到来自被订阅频道的消息,我们把这些消息称为频道消息。与订阅消息一样,频道消息也是由3个元素组成的:

  • 消息的第1个元素为"message",用于表明该消息是一条频道消息而非订阅消息。
  • 消息的第2个元素为消息的来源频道,用于表明消息来自于哪个频道。
  • 消息的第3个元素为消息的正文,也就是消息的真正内容。

示例:


接收者收到了这条频道消息:


1.3 UNSUBSCRIBE:退订频道

用户在使用SUBSCRIBE命令订阅一个或多个频道之后,如果不想再收到某个频道的消息,那么可以使用UNSUBSCRIBE命令退订指定的频道。

语法:


UNSUBSCRIBE命令允许用户给定任意多个频道。如果用户没有给定任何频道,直接以无参数方式执行UNSUBSCRIBE命令,那么命令将退订当前客户端已经订阅的所有频道。

示例:

如果我们想要让客户端退订"news.it"频道和"news.sport"频道,那么可以执行以下命令:

与此类似,如果我们想要让客户端退订目前已订阅的所有频道,那么只需要以无参数方式直接执行UNSUBSCRIBE命令即可:

客户端在每次退订频道之后,都会收到服务器发来的退订消息,这条消息由3个元素组成:

  • 第1个元素是"unsubscribe",表明该消息是一条由退订操作产生的消息。
  • 第2个元素是被退订频道的名字。
  • 第3个元素是客户端在执行退订操作之后,目前仍在订阅的频道数量。

UNSUBSCRIBE命令在不同客户端中的应用:

虽然Redis提供了用于退订频道的UNSUBSCRIBE命令,但由于各个客户端对于发布与订阅功能的支持方式不尽相同,所以并非所有客户端都可以使用UNSUBSCRIBE命令执行退订操作。

比如,Redis自带的命令行客户端redis-cli在执行SUBSCRIBE命令之后就会进入阻塞状态,无法再执行任何其他命令,用户只能通过同时按下Ctrl键和C键强制退出redis-cli程序,所以这个客户端实际上并不会用到UNSUBSCRIBE命令。


1.4 PSUBSCRIBE:订阅模式

用户可以通过执行PSUBSCRIBE命令,让客户端订阅给定的一个或多个模式。

语法:

传入PSUBSCRIBE命令的每个pattern参数都可以是一个全局风格的匹配符,比如"news.*"模式可以匹配所有以"news."为前缀的频道,而"news.[ie]t"模式则可以匹配"news.it"频道和"news.et"频道,诸如此类。

示例:

举个例子,如果我们想要订阅所有带有"news."前缀的频道的消息,那么可以执行以下命令:

  • 第1个元素是"psubscribe",它表明这条消息是由PSUBSCRIBE命令引发的订阅消息。
  • 第2个元素是被订阅的模式。
  • 第3个元素是客户端目前订阅的模式数量。

比如在上面执行的PSUBSCRIBE命令中,订阅消息的第2个元素为"news.*",第3个元素为数字1,这表明客户端目前只订阅了"news.*"这一个模式。

如果我们使用PSUBSCRIBE命令同时订阅多个模式,那么客户端将会收到多条模式订阅消息,就像这样:


1.4.1 接收模式消息

客户端在订阅模式之后,就会收到所有与模式相匹配的频道的消息,我们把这些消息称为模式消息。模式消息与之前展示的订阅消息以及频道消息稍微有些不同,它由4个元素组成:

  • 消息的第1个元素为"pmessage",它表示这是一条模式消息而不是订阅消息或者频道消息。
  • 消息的第2个元素为被匹配的模式,而第3个元素则是与模式相匹配的频道。
  • 消息的第4个元素为消息的正文,也就是消息的真正内容。

示例:


接收者收到了这条频道消息:


1.5 PUNSUBSCRIBE:退订模式

与退订频道的UNSUBSCRIBE命令类似,Redis也提供了用于退订模式的PUNSUBSCRIBE命令:
这个命令允许用户输入任意多个想要退订的模式,如果用户没有给定任何模式,那么命令将退订当前客户端已订阅的所有模式。

示例:

如果我们想要退订"news.*"模式,那么可以执行以下命令:
如果我们想要退订所有模式,那么可以执行以下命令:


PUNSUBSCRIBE命令每次退订一个模式之后,都会向客户端返回一条退订消息,该消息由3个元素组成:

  • 第1个元素是"punsubscribe",用于表明该消息是一条由PUNSUBSCRIBE命令引起的退订消息。
  • 第2个元素是被退订的模式。
  • 第3个元素是客户端在执行当前这个退订操作之后,仍在订阅的模式数量。

PUNSUBSCRIBE命令在不同客户端中的应用:

与UNSUBSCRIBE命令一样,各个客户端对于PUNSUBSCRIBE命令的需求也是不同的,有些客户端需要用到PUNSUBSCRIBE命令,而有些客户端则不需要。

举个例子,Redis自带的命令行客户端redis-cli在执行PSUBSCRIBE命令之后就会进入阻塞状态,只能通过同时按下Ctrl键和C键来退出程序,因此它并不需要用到PUNSUBSCRIBE命令。


1.6 PUBSUB:查看发布与订阅的相关信息


1.6.1 查看被订阅的频道

用户可以通过执行PUBSUB CHANNELS命令来列出目前被订阅的所有频道,如果给定了可选的pattern参数,那么命令只会列出与给定模式相匹配的频道。

示例:

以下代码展示了该如何列出目前被订阅的所有频道:

而以下代码则展示了如何列出所有以"news."开头的被订阅频道:


1.6.2 查看频道的订阅者数量

用户可以通过执行PUBSUB NUMSUB命令,查看任意多个给定频道的订阅者数量:

示例:

如果我们要查看"news.it"、"news.sport"和"notification.new_email"这3个频道的订阅者数量,那么可以执行以下命令:


1.6.3 查看被订阅模式的总数量

通过执行PUBSUB NUMPAT命令,用户可以看到目前被订阅模式的总数量:

示例:

比如以下代码就显示了服务器目前共有2个模式被订阅:


1.7 发布与订阅重点回顾

  • Redis的发布与订阅功能可以让客户端通过广播方式,将消息同时发送给可能存在的多个客户端,并且发送消息的客户端不需要知道接收消息的客户端的具体信息。
  • 在Redis中,客户端可以通过订阅特定的频道来接收发送至该频道的消息,我们把这些订阅频道的客户端称为订阅者。一个频道可以有任意多个订阅者,而一个订阅者也可以同时订阅任意多个频道。
  • 除此之外,客户端还可以通过向频道发送消息的方式,将消息发送给频道的所有订阅者,我们把这些发送消息的客户端称为发送者。
  • 除了订阅频道之外,客户端还可以通过订阅模式来接收消息:每当发布者向某个频道发送消息的时候,不仅频道的订阅者会收到消息,与频道匹配的所有模式的订阅者也会收到消息。


以上是关于Redis 进阶 -- 发布与订阅的主要内容,如果未能解决你的问题,请参考以下文章

Redis 进阶 -- 发布与订阅

Redis学习之旅--订阅与发布

Redis的发布订阅

Redis入门——Redis发布订阅

Redis 发布订阅

Redis - 发布/订阅