Redis - 发布/订阅模式
Redis 提供了一组命令可以让开发者实现 “发布/订阅” 模式。“发布/订阅” 可以实现进程间的消息传递,其原理是这样的:
“发布/订阅” 模式中包含两种角色,分别是发布者和订阅者。订阅者可以订阅一个或若干个频道(channel),而发布者可以向指定的频道发送消息,所有订阅此频道的订阅者都会收到此消息。
发布者发布消息的命令是 PUBLISH,用法是 PUBLISH channel message,如向 channel.1 说一声 “hi”:
redis> PUBLISH channel.1 hi
(integer) 0
这样消息就发出去了。PUBLISH 命令的返回值表示接收到这条消息的订阅者数量。因为此时没有客户端订阅 channel.1,所以返回 0。发出去的消息不会被持久化,也就是说当有客户端订阅 channel.1 后只能收到后续发布到该频道的消息,之前发送的就收不到了。
订阅频道的命令是 SUBSCRIBE,可以同时订阅多个频道,用法是 SUBSCRIBE channel [channel ...]。现在新开一个 redis-cli 实例 A,用它来订阅 channel.1:
redis A> SUBSCRIBE channel.1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel.1"
3) (integer) 1
执行 SUBSCRIBE 命令后客户端会进入订阅状态,处于此状态下客户端不能使用除 SUBSCRIBE、UNSUBSCRIBE、PSUBSCRIBE 和 PUNSUBSCRIBE 这 4 个属于 “发布/订阅” 模式的命令之外的命令,否则会报错。
进入订阅状态后客户端可能收到 3 种类型的回复。每种类型的回复都包含 3 个值,第一个值是消息的类型,根据消息类型不同,第二、三个值的含义也不同。消息类型可能的取值有以下 3 个。
(1)subscribe。表示订阅成功的反馈信息。第二个值是订阅成功的频道名称,第三个值是当前客户端订阅的频道数量。
(2)message。表示接收到的消息。第二个值表示产生消息的频道名称,第三个值是消息的内容。
(3)unsubscribe。表示成功取消订阅某个频道。第二个值是对应的频道名称,第三个值是当前客户端订阅的频道数量,当次值为 0 时客户端会退出订阅状态,之后就可以执行其他非 “发布/订阅” 模式的命令了。
上例中当实例 A 订阅了 channel.1 进入订阅状态后收到了一条 subscribe 类型的回复,这时我们打开另一 redis-cli 实例 B,并向 channel.1 发送一条消息:
redis B> PUBLISH channel.1 hi!
(integer) 1
返回值为 1,表示有一个客户端订阅了 channel.1,此时实例 A 收到了类型为 message 的回复:
1) "message"
2) "channel.1"
3) "hi!"
使用 UNSUBSCRIBE 命令可以取消指定的频道,用法为 UNSUBSCRIBE [channel [channel ...]],如果不指定频道则会取消订阅所有频道。由于 redis-cli 的限制,无法在其中测试 UNSUBSCRIBE 命令。
按照规则订阅
除了可以使用 SUBSCRIBE 命令订阅指定名称的频道外,还可以使用 PSUBSCRIBE 命令订阅指定的规则。规则支持 glob 风格通配符格式,下面新打开一个 redis-cli 实例 C 进行演示:
redis C> PSUBSCRIBE channel.?*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "channel.?*"
3) (integer) 1
规则 channel.?* 可以匹配 channel.1 和 channel.10,但不会匹配 channel.。这时在实例 B 中发布消息:
127.0.0.1:6379> PUBLISH channel.1 hi!
(integer) 2
返回结果为 2 是因为实例 A 和实例 C 两个客户端都订阅了 channel.1 频道。实例 C 接收到的回复是:
1) "pmessage"
2) "channel.?*"
3) "channel.1"
4) "hi!"
第一个值表示这条消息是通过 PSUBSCRIBE 命令订阅频道而收到的,第二个值表示订阅时使用的通配符,第三个值表示实际收到消息的频道命令,第三个值则是消息内容。
使用 PSUBSCRIBE 命令可以重复订阅一个频道,如某客户端执行 PSUBSCRIBE channel.? channel.?*,这时向 channel.2 发布消息后该客户端会收到两条消息,而同时 PUBLISH 命令返回的值也是 2 而不是 1。同样的,如果有另一客户端执行了 SUBSCRIBE channel 10 和 PSUBSCRIBE channel.?* 的话,向 channel.10 发送命令该客户端也会收到两条消息(但是是两种类型:message 和 pmessage),同时 PUBLISH 命令会返回 2。
PUNSUBSCRIBE 命令可以退订指定的规则,用法是 PUNSUBSCRIBE [pattern [pattern ...]],如果没有参数则会退订所有规则。
使用 PUNSUBSCRIBE 命令只能退订通过 PSUBSCRIBE 命令订阅的规则,不会影响直接通过 SUBSCRIBE 命令订阅的频道;同样 UNSUBSCRIBE 命令也不会影响通过 PSUBSCRIBE 命令订阅的规则。另外容易出错的一点是使用 PUNSUBSCRIBE 命令退订某个规则时不会将其中的通配符展开,而是进行严格的字符串匹配,所以 PUNSUBSCRIBE * 无法退订 channel.* 规则,而是必须使用 PUNSUBSCRIBE channel.* 才能退订。
Redis - 发布/订阅模式的更多相关文章
- SpringBoot Redis 发布订阅模式 Pub/Sub
SpringBoot Redis 发布订阅模式 Pub/Sub 注意:redis的发布订阅模式不可以将消息进行持久化,订阅者发生网络断开.宕机等可能导致错过消息. Redis命令行下使用发布订阅 pu ...
- redis发布/订阅模式
其实在很多的MQ产品中都存在这样的一个模式,我们常听到的一个例子 就是邮件订阅的场景,什么意思呢,也就是说100个人订阅了你的博客,如果博主发表了文章,那么100个人就会同时收到通知邮件,除了这个 场 ...
- 使用EventBus + Redis发布订阅模式提升业务执行性能
前言 最近一直奔波于面试,面了几家公司的研发.有让我受益颇多的面试经验,也有让我感觉浪费时间的面试经历~因为疫情原因,最近宅在家里也没事,就想着使用Redis配合事件总线去实现下具体的业务. 需求 一 ...
- redis 发布/订阅 模式
发布/订阅模式的命令如下: * 进入发布订阅模式的客户端,不能执行除发布订阅模式以上命令的其他命令,否则出错.
- 使用EventBus + Redis发布订阅模式提升业务执行性能(下)
前言 上一篇博客上已经实现了使用EventBus对具体事件行为的分发处理,某种程度上也算是基于事件驱动思想编程了.但是如上篇博客结尾处一样,我们源码的执行效率依然达不到心里预期.在下单流程里我们明显可 ...
- 把酒言欢话聊天,基于Vue3.0+Tornado6.1+Redis发布订阅(pubsub)模式打造异步非阻塞(aioredis)实时(websocket)通信聊天系统
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_202 "表达欲"是人类成长史上的强大"源动力",恩格斯早就直截了当地指出,处在蒙昧时代即低 ...
- Redis 发布订阅,小功能大用处,真没那么废材!
今天小黑哥来跟大家介绍一下 Redis 发布/订阅功能. 也许有的小伙伴对这个功能比较陌生,不太清楚这个功能是干什么的,没关系小黑哥先来举个例子. 假设我们有这么一个业务场景,在网站下单支付以后,需要 ...
- 15天玩转redis —— 第九篇 发布/订阅模式
本系列已经过半了,这一篇我们来看看redis好玩的发布订阅模式,其实在很多的MQ产品中都存在这样的一个模式,我们常听到的一个例子 就是邮件订阅的场景,什么意思呢,也就是说100个人订阅了你的博客,如果 ...
- redis的发布订阅模式
概要 redis的每个server实例都维护着一个保存服务器状态的redisServer结构 struct redisServer { /* Pubsub */ // 字典,键为频道, ...
随机推荐
- 转载LINQ系列OrderBy(), ThenBy()简介
前言 前面两篇分别介绍了 Where() 与 Select() ,这篇则是要介绍 OrderBy() 与 ThenBy() ,这几个东西看起来最像 SQL 上会用到的语法,但切记一点,这边介绍的是 L ...
- 2015年必火的五个Html5移动开发工具推荐
NO.1 DCloudHBuilder:基于HTML5开发工具 中文官网:http://www.dcloud.io/ DCloudHBuilder:基于HTML5开发工具是当前最快的HTML开发工 ...
- HDU 3687 National Day Parade (暴力)
题意:给定 n 个人,在 n 列,问你移动最少的距离,使得他们形成一个n*n的矩阵. 析:这个题本来是要找中位数的,但是有特殊情况,所以改成暴力了,时间也很短,就是从第一个能够放左角的位置开始找,取最 ...
- 编译小结(6)认识Automake
我前面说了很多如何用gcc或 Makefile怎么编译的东东,但在Linux下装过软件的都应当见过,很多源码安装的包是用Automake 来编译的.输入下"./configur ...
- PostgreSQL中如何查询在当前的哪个数据库中
[pgsql@localhost bin]$ ./psql -d tester psql () Type "help" for help. tester=# select curr ...
- java泛型的讲解
java泛型 什么是泛型? 泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类.可以把类型参数看作是使用参数化类型时指 ...
- C#-datagriview的表头高度的设置
- Codeforces Gym 100610 Problem K. Kitchen Robot 状压DP
Problem K. Kitchen Robot Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/10061 ...
- C# Process 类的思考
在这里,我先给自己留个印象 下面我们用C#实现一个调用Dos命令的小程序,让大家对系统进程能有个直观的了解.要使用Process类,首先要引入System.Diagnostic命名空间,然后定义一个新 ...
- 动态创建组件TEdit
//动态创建组件TEdit procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftSt ...