Redis不仅仅是Key-Value数据库,而且也提供发布/订阅功能。发布订阅分为两种方式,一种是直接订阅频道,即用户订阅到一个频道名,那么发给该频道名的消息将推送给订阅者。另一种方式是采用正则匹配的方式。在实现中,发送者不是将信息直接发送给特定的接收者,而是将信息发送给频道,然后由频道将信息转发给所有对这个频道感兴趣的订阅者。
发送者无须知道任何关于订阅者的信息,而订阅者也无须知道是那个客户端给它发送信息,它只要关注自己感兴趣的频道即可。对发布者和订阅者进行解构,可以极大地提高系统的扩展性。
图:订阅管道
比如说,要订阅频道 finance 和 it,客户端可以使用频道名字作为参数来调用 subscribe命令:
redis> subscribe finance it
当有客户端发送信息到这些频道时,Redis会将传入的信息推送到所有订阅这些频道的客户端里面。
频道转发的每条信息都是一条带有三个元素的多条信息。信息的第一个元素标识了信息的类型,可选值如下:
表示当前客户端成功地订阅了信息,第二个元素表所订阅的频道名称,第三个元素则记录了目前客户端已订阅频道的总数。
127.0.0.1:6379> subscribe finance it Reading messages... (press Ctrl-C to quit) 1) "subscribe" # 订阅第一个频道 2) "finance" # 频道名称 3) (integer) 1 # 频道总数 1) "subscribe" # 订阅第二个频道 2) "it" 3) (integer) 2
表示当前客户端成功地退订了信息,第二个元素表示退订的频道名称,第三个元素记录了客户端目前仍在订阅的频道数量。当客户端订阅的频道数量降为0时,客户端不再订阅任何频道,它可以像往常一样,执行任何Redis命令。
表示这条信息是由某个客户端执行publish命令所发送的消息, 即真正的信息。信息的第二个元素是信息来源的频道,而第三个元素则是信息的内容。
1) "message" # 表示消息 2) "it" # 频道名称 3) "hello" # 消息内容
实例1:订阅两个频道,然后发送信息到频道。
第一步:订阅first和second频道,如下:
第二步:发布消息到second频道,如下:
那么之前订阅了second频道的客户端将收到以下信息:
实例2:订阅者退订所有已经订阅了的频道。
redis> unsubscribe # 退订订阅频道 1) "unsubscribe" 2) "second" 3) (integer) 1 1) "unsubscribe" 2) "first" 3) (integer) 0
Redis的发布与订阅实现支持模式匹配:客户端可以订阅一个带 * 号的模式,如果某个/某些频道的名字和这个模式匹配,那么当有信息发送给这个/这些频道的时候,客户端也会收到这个/这些频道的信息。比如说:
执行上面命令的客户端将收到news.cup、news.it等频道的信息。客户端订阅的模式里面可以包含多个glob风格的通配符,比如*、?和[...]等。
执行下面命令将退订news.*模式,其他已订阅的模式不会被影响。如下:
redis> punsubscribe news.*
订阅模式与订阅频道接收到的信息格式不太一样,实例如下:
第一步:监听“news.*”匹配模式,如下图:
第二步:发布一个消息到“news.com”频道,消息内容为“hello”。如下图:
接受到的信息如下:
其中:
1) “pmessage” 通过订阅模式接收到的信息的类型为pmessage。这代表有某个客户端通过 publish 向某个频道发送了信息, 而这个频道刚好匹配了当前客户端所订阅的某个模式。
2) “news.*” 被匹配的模式。
3) “news.com” 被匹配的频道的名字。
4) “hello” 消息的实际内容。