Redis发布订阅

*Pub/Sub

SUBSCRIBE, UNSUBSCRIBEPUBLISH 实现了 发布/订阅消息范例,发送者 (publishers) 不直接向特定的接收者发送消息 (subscribers),而是发布消息到频道(channel),不关心有没有订阅者。订阅者订阅关注一个或多个频道(channel),并且只接收他关注的消息,不管发布者是不是存在。发布者和订阅者的解耦提供了更大的伸缩性、更动态的网络拓扑。

例如,为了订阅通道 foo 和 bar ,客户端可以使用通道名字作为参数来调用 SUBSCRIBE 命令:

SUBSCRIBE foo bar

当有客户端发送消息到这些频道时,Redis将会推送传入的消息给所有订阅这些频道的客户端。

正在订阅频道的客户端不应该发送除了订阅或取消订阅以外的命令。订阅和退订操作的执行结果以消息的形式返回,客户端可以读取收到消息的第一个元素来区分收到的是消息类型,还是订阅和退订操作执行结果。订阅客户端能使用的命令是 SUBSCRIBE, PSUBSCRIBE, UNSUBSCRIBE, PUNSUBSCRIBE, PINGQUIT.

*推送消息的格式

消息是带有三个元素的Array repl

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

  • subscribe: 表示成功订阅到以第二个返回元素命名的频道。第三个元素表示客户端当前订阅频道总数。

  • unsubscribe: 表示成功退订以第二个返回元素命名的频道。第三个元素表示客户端当前订阅频道总数。当第三个参数为零的时候,表示客户端已退出Pub/Sub状态,不再订阅任何频道,可以发送订阅和退订以外的Redis 命令。

  • message: 表示收到其它某一个客户端用 PUBLISH 发布的消息,第二个元素是来源频道的名字,第三个参数是消息实际内容。

*数据库&作用域

Pub/Sub 和键空间没有关系,在任何层面上都没有交互,跟数据库number也没有关系。

向db10发布消息也能再db1订阅到消息。

如果您要某种范围,请在通道前加上环境名称(测试,生产……)

*协议实例

第一个客户端执行订阅:

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 Pub/Sub 的实现支持模式匹配。客户端可以通过订阅glob风格的模式来接收所有频道名字与模式匹配的消息。

例如:

PSUBSCRIBE news.*

将会收到所有news.开头的频道消息,像news.art.figurative, news.music.jazz, 等。redis支持所有glob风格的模式,也支持多个通配符。

PUNSUBSCRIBE news.*

unsubscribe 退订模式。不会影响其它的订阅者。

通过模式匹配接收的消息使用不同的格式发送:

  • 消息的格式是 pmessage: 它是由另一个客户端使用 PUBLISH 命令发送的消息,并且匹配当前客户端订阅的一个模式匹配。第二个元素是匹配的原始模式,第三个元素是匹配的频道的名字,最后一个元素是实际的消息内容。

 SUBSCRIBE 和 UNSUBSCRIBE与 PSUBSCRIBE 和 PUNSUBSCRIBE 命令类似,系统可以通过第一个元素来识别是那种消息。

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

如果客户端订阅的多个模式匹配发布的消息, 或者订阅的模式和频道都匹配消息,这个消息会被客户端收到多次。例如:

SUBSCRIBE foo
PSUBSCRIBE f*

如果有消息被发送到频道 foo, 客户端会收到两个消息:一个是 message 类型,另一个是 pmessage 类型。

*带有模式匹配的订阅计数的含义

在 subscribe, unsubscribe, psubscribe 和 punsubscribe 的消息类型中,最后一个参数是仍在活动的订阅者数量。它表示客户端当前订阅的频道和模式的总数。当客户端退订所有模式和频道,订阅总数变为0之后这个客户端会退出 Pub/Sub 状态。

*编程实例

Pieter Noordhuis 提供了一个使用  EventMachine 和 Redis 编写的 高性能多用户网页聊天 程序。

*客户端lib实现提示

因为所有的消息都包含订阅信息,所以客户端lib可以利用hash把原始订阅信息和回调绑定,当收到一个消息时只花费O(1) 查找已注册的回调来投递消息。