查看“Redis:发布/订阅(pub/sub)”的源代码
←
Redis:发布/订阅(pub/sub)
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:Redis]] __TOC__ == 关于 == SUBSCRIBE 、 UNSUBSCRIBE 和 PUBLISH 三个命令实现了发布与订阅信息泛型(Publish/Subscribe messaging paradigm),在这个实现中: 1、发送者(发送信息的客户端)不是将信息直接发送给特定的接收者(接收信息的客户端),而是将信息发送给频道(channel),然后由频道将信息转发给所有对这个频道感兴趣的订阅者。 2、发送者无须知道任何关于订阅者的信息,而订阅者也无须知道是那个客户端给它发送信息,它只要关注自己感兴趣的频道即可。 对发布者和订阅者进行解构(decoupling), 可以极大地提高系统的扩展性(scalability), 并得到一个更动态的网络拓扑(network topology)。 发布订阅(pub/sub)是一种消息通信模式:发送者(publish)发送消息,订阅者(subscribe)接收消息。 :[[File:redis发布.png|left|thumb|200px|发布]] [[File:reids订阅.png|none|thumb|300px|订阅]] === “发布订阅”与“消息队列” === 发布订阅也叫“'''生产者消费者'''”模式,是实现“'''消息队列'''”的一种方式。基于消息队列,可以实现系统解耦、削峰填谷,顶住流量洪峰。 * redis 的主业目前是基于键值对的数据存储、缓存等,消息队列可能是 redis 的一种尝试; * 常用的流行的消息队列有:“'''ActiveMQ'''”、“'''RabbitMQ'''”等; 消息队列的三要素: # 生产者(producer) # 消费者(consumer) # 消息服务(broker) == Pub/Sub 命令 == 正在订阅频道的客户端不应该发送除下述之外的其他命令: {| class="wikitable" |+ Redis:发布/订阅 命令 ! !! 命令 !! 描述 |- | rowspan="2" | 订阅频道 | SUBSCRIBE <channel> [<channel> ...] || '''订阅'''给定的一个或多个频道的信息。 * 返回值:“信息”(参见下节“信息的格式”); |- | UNSUBSCRIBE [<channel> [<channel> ...]] || '''退订'''给定的频道。 * 返回值在不同的客户端中有不同的表现; |- | rowspan="2" | 订阅模式 | PSUBSCRIBE <pattern> [<pattern> ...] || '''订阅'''一个或多个符合给定模式的频道。 * 返回值:“信息”; |- | PUNSUBSCRIBE [<pattern> [<pattern> ...]] || '''退订'''给定模式的频道。 * 返回值在不同的客户端中有不同的表现; |- | 发布 | PUBLISH <channel> <message> || 将信息'''发布'''到指定的频道。 * 返回值:接收到信息 <message> 的订阅者数量。 |- | 系统状态 | PUBSUB <subcommand> [<argument> [<argument> ...]] || 它是一个查看订阅与发布系统状态的内省命令,由数个不同格式的子命令组成。 |} * 客户端订阅的模式里面可以包含多个 glob 风格的通配符, 比如: '''*''' 、 '''?''' 和 '''[...]''',等等。 * 在执行 SUBSCRIBE、UNSUBSCRIBE、PSUBSCRIBE 和 PUNSUBSCRIBE 命令时,返回结果的最后一个元素是客户端目前'''仍在订阅的频道和模式总数'''。 ** 当客户端退订所有频道和模式,也即是这个总数值下降为 0 的时候,客户端将退出订阅与发布状态。 === PUBSUB === PUBSUB 有多个可用的子命令: # <syntaxhighlight lang="bash" highlight=""> # 列出当前的活跃频道: PUBSUB CHANNELS [pattern] # 返回值:一个由活跃频道组成的列表。 </syntaxhighlight> #* 活跃频道:指的是那些至少有一个订阅者的频道(订阅模式的客户端不计算在内)。 #* 如果给出 pattern 参数,那么只列出和 pattern 相匹配的活跃频道,否则列出订阅与发布系统中的所有活跃频道。 #* 即使一个频道有多个订阅者,它也只输出一次。 #: 示例: #: <syntaxhighlight lang="bash" highlight=""> # client-1 订阅 news.it 和 news.sport 两个频道 # client-2 订阅 news.it 和 news.internet 两个频道 # 使用 client-3 打印所有活跃频道: redis> PUBSUB CHANNELS 1) "news.sport" 2) "news.internet" 3) "news.it" # 打印匹配的活跃频道: redis> PUBSUB CHANNELS news.i* 1) "news.internet" 2) "news.it" </syntaxhighlight> # <syntaxhighlight lang="bash" highlight=""> # 返回给定频道的订阅者数量(订阅模式的客户端不计算在内): PUBSUB NUMSUB [channel-1 ... channel-N] # 返回值:一个多条批量回复(Multi-bulk reply),回复中包含给定的频道,以及频道的订阅者数量。 # 格式为“频道channel-1,channel-1的订阅者数量,频道channel-2,channel-2的订阅者数量 . . .”。 </syntaxhighlight> #* 回复中频道的排列顺序和执行命令时给定频道的排列顺序一致。 #* 不给定任何频道而直接调用这个命令也是可以的,在这种情况下,命令只返回一个空列表。 #: 示例: #: <syntaxhighlight lang="bash" highlight=""> # client-1 订阅 news.it 和 news.sport 两个频道 # client-2 订阅 news.it 和 news.internet 两个频道 # 使用 client-3 打印各个频道的订阅者数量: redis> PUBSUB NUMSUB news.it news.internet news.sport news.music 1) "news.it" # 频道 2) "2" # 订阅该频道的客户端数量 3) "news.internet" 4) "1" 5) "news.sport" 6) "1" 7) "news.music" # 没有任何订阅者 8) "0" </syntaxhighlight> # <syntaxhighlight lang="bash" highlight=""> # 返回订阅模式的数量: PUBSUB NUMPAT # 返回值:一个整数回复(Integer reply)。 </syntaxhighlight> #* 这个命令返回的不是订阅模式的客户端的数量,而是“所有客户端订阅的模式的数量总和”(多个客户端订阅相同的模式时,会被重复计算)。 #: 示例: #: <syntaxhighlight lang="bash" highlight=""> # client-1 订阅 news.* 和 discount.* 两个模式 # client-2 订阅 tweet.* 一个模式 # 使用 client-3 打印当前订阅模式的数量: redis> PUBSUB NUMPAT (integer) 3 # 再新建一个客户端 client-4 ,让它也订阅 news.* 频道 # 再使用 client-3 打印当前订阅模式的数量: redis> PUBSUB NUMPAT (integer) 4 </syntaxhighlight> == 频道和模式 == === 订阅频道 === <syntaxhighlight lang="java" highlight=""> // 订阅 subscribe <channel> [<channel> ...] // 发布 publish <channel> <message> </syntaxhighlight> (以命令行模拟实现): # 开启 4 个 redis 客户端(“./redis-cli”),如上图,3 个客户端作为消息订阅者,1 个为消息发布者: # 让 3 个消息订阅者订阅某个频道主题:“'''<code>subscribe channelTest</code>'''”; #: [[File:redis订阅channelTest.jpg|800px]] # 让 1 个消息发布者向频道主题上发布消息:“'''<code>publish channelTest message123</code>'''”; #: [[File:redis发布消息到channelTest.jpg|800px]] === 订阅模式 === <syntaxhighlight lang="java" highlight=""> // 订阅 psubscribe <pattern> [<pattern> ...] // 发布 publish <channel> <message> </syntaxhighlight> (以命令行模拟实现): # 订阅匹配模式的频道:“'''<code>psubscribe chan*</code>'''” #:[[File:redis订阅(psubscribe).jpg|800px]] # 发布: #:[[File:redis发布(psubscribe).jpg|800px]] == 信息的格式 == 频道转发的每条信息都是一条带有三个元素的多条批量回复(multi-bulk reply)。 信息类型:(信息的第一个元素) # “'''subscribe'''”:表示当前客户端成功地订阅了(信息第二个元素所指示的)频道。 #: 第二个元素:订阅的频道; #: 第三个元素:客户端目前已订阅的频道数量。 # “'''unsubscribe'''”:表示当前客户端成功地退订了(信息第二个元素所指示的)频道。 #: 第二个元素:退订的频道; #: 第三个元素:客户端目前仍在订阅的频道数量。 #* 当客户端订阅的频道数量降为 0 时,客户端不再订阅任何频道,它可以像往常一样,执行任何 Redis 命令。 # “'''message'''”:表示这条信息是由某个客户端执行 PUBLISH 命令所发送的,真正的信息。 #: 第二个元素:信息来源的频道; #: 第三个元素:信息的内容。 # “'''pmessage '''”:表示有某个客户端通过 PUBLISH 向某个频道发送了信息,而这个频道刚好匹配了当前客户端所订阅的某个模式。 #: 第二个元素:被匹配的模式; #: 第三个元素:被匹配的频道的名字; #: 最后一个元素:信息的实际内容。 示例: # subscribe 类型的信息: #: <syntaxhighlight lang="bash" highlight=""> redis> SUBSCRIBE first second 1) "subscribe" 2) "first" 3) (integer) 1 1) "subscribe" 2) "second" 3) (integer) 2 </syntaxhighlight> # message 类型的信息: #: 客户端B订阅频道、客户端A项频道发送数据后,客户端B所接受到信息 #: <syntaxhighlight lang="bash" highlight=""> redis> SUBSCRIBE hello 1) "subscribe" 2) "hello" 3) (integer) 1 1) "message" 2) "second" 3) "hello" </syntaxhighlight> # unsubscribe 类型的信息: #: <syntaxhighlight lang="bash" highlight=""> redis> UNSUBSCRIBE 1) "unsubscribe" 2) "second" 3) (integer) 1 1) "unsubscribe" 2) "first" 3) (integer) 0 </syntaxhighlight> == FAQ == === 通过频道和模式接收同一条信息 === 如果客户端订阅的多个模式匹配了同一个频道,或者客户端同时订阅了某个频道、以及匹配这个频道的某个模式,那么它可能会多次接收到同一条信息。 示例: : 如果客户端执行了以下命令: : <syntaxhighlight lang="bash" highlight=""> SUBSCRIBE foo PSUBSCRIBE f* </syntaxhighlight> : 当有信息发送到频道 foo 时,客户端将收到两条信息:一条来自频道 foo,信息类型为 message;另一条来自模式 f*,信息类型为 pmessage 。
返回至“
Redis:发布/订阅(pub/sub)
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息