1、“发布/订阅”模式
“发布/订阅”(publish/subscribe)是一种消息通信模式,可以实现进程间通信,订阅者可以订阅一个或多个频道(channel),而发布者可以向指定的频道发送消息,所有订阅同频道的订阅者都会收到相同的信息。
1.1 命令介绍
· PSUBSCRIBE pattern [pattern1 ....]
- 说明:订阅一个或多个符合给定模式的频道,每个模式以*作为匹配符
- 参数:pattern(给定的模式)
- 返回:接受到的信息
· PUNSUBSCRIBE pattern [pattern1 ....]
- 说明:用于退订所有给定模式的频道
- 参数:pattern(给定的模式)
- 返回:这个命令在不同的客户端中有不同的表现。
· SUBSCRIBE channel [channel1 ...]
- 说明:用于订阅给定的一个或多个频道的信息
- 参数:channel(给定的频道名)
- 返回:接收到的信息
· UNSUBSCRIBE channel [channel1 ...]
- 说明:用于退订给定的一个或多个频道的信息
- 参数:channel(给定的频道名)
- 返回:这个命令在不同的客户端中有不同的表现
· PUBLISH channel message
- 说明:用于将信息发送到指定的频道
- 参数:channel(频道名称),message(将要发送的信息)
- 返回:接收到此消息的订阅者数量
· PUBSUB < subcommand > argument [argument1 ....]
- 说明:用于查看订阅与发布系统状态的内省命令,它由数个不同格式的子命令组成
- 参数:subcommand(子命令),argument(子命令参数)
- 返回:列出当前的活跃频道
- 子命令如下
subcommand | argument | 说明 |
CHANNELS | [pattern] | 指定pattern:只列出和给定模式 pattern 相匹配的那些活跃频道 不指定pattern:列出订阅与发布系统中的所有活跃频道。 |
NUMSUB | Channel | 返回指定频道的订阅数量。 |
NUMPAT | NUMPAT | 返回订阅模式的数量,注意:这个命令返回的不是订阅模式的客户端的数量, 而是客户端订阅的所有模式的数量总和 |
1.2命令实践
PUBLISH
- 将信息 message 发送到指定的频道 channel。返回收到消息的客户端数量。
SUBSCRIBE
- 订阅给指定频道的信息。
- 一旦客户端进入订阅状态,客户端就只可接受订阅相关的命令SUBSCRIBE、PSUBSCRIBE、UNSUBSCRIBE和PUNSUBSCRIBE除了这些命令,其他命令一律失效。
UNSUBSCRIBE
取消订阅指定的频道,如果不指定,则取消订阅所有的频道。
127.0.0.1:6379> PUBLISH test.1 test
(integer) 0 //0个客户端收到消息
127.0.0.1:6379> SUBSCRIBE test.1
Reading messages... (press Ctrl-C to quit)
1) "subscribe" //"subscribe"表示订阅成功的信息
2) "test.1" //表示订阅成功的频道
3) (integer) 1 //表示当前订阅客户端的数量
//当发布者发布消息时,订阅者会收到如下消息
1) "message" //表示接收到消息
2) "test.1" //表示产生消息的频道
3) "test" //表示消息的内容
//当订阅者取消订阅时会显示如下:
127.0.0.1:6379> UNSUBSCRIBE test.1
1) "unsubscribe" //表示成功取消订阅
2) "test.1" //表示取消订阅的频道
3) (integer) 0 //表示当前订阅客户端的数量
PSUBSCRIBE
- 订阅给定的模式(patterns)。
PUNSUBSCRIBE
- 可以退订指定的规则,如果没有参数会退订所有的规则。
127.0.0.1:6379> PSUBSCRIBE channel1.*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "channel1.*"
3) (integer) 1
//等待发布者发布消息
127.0.0.1:6379> PUBLISH channel1.1 test1.1
(integer) 1 //发布者在channel1.1发布消息
1) "pmessage" //表示通过PSUBSCRIBE命令订阅而收到的
2) "channel1.*" //表示订阅时使用的通配符
3) "channel1.1" //表示收到消息的频道
4) "test1.1" //表示消息内容
127.0.0.1:6379> PUBLISH channel1.2 test1.2
(integer) 1 //发布者在channel1.2发布消息
1) "pmessage"
2) "channel1.*"
3) "channel1.2"
4) "test1.2"
127.0.0.1:6379> PUBLISH channel1.3 test1.3
(integer) 1 //发布者在channel1.3发布消息
1) "pmessage"
2) "channel1.*"
3) "channel1.3"
4) "test1.3"
127.0.0.1:6379> PUNSUBSCRIBE channal1.*
1) "punsubscribe" //退订成功
2) "channal1.*" //退订规则的通配符
3) (integer) 0 //表示当前订阅客户端的数量
注意:
- 使用PUNSUBSCRIBE命令只能退订通过PSUBSCRIBE命令订阅的规则,不会影响SUBSCRIBE订阅的频道。
- 使用PUNSUBSCRIBE命令退订某个规则时不能使用通配符展开,而是严格的进行字符串匹配。
2、Pub/Sub与Redis Keyspace Notifications
我们的需求是使用redis的Pub/Sub与Redis Keyspace Notifications实现一个定时任务,同时实现任务的发送者与任务执行者之间的解耦。
2.1 说明
当redis中的一些事件发生时,如key过期,可以被删除等,我可以让redis一旦发生这些事件时就利用pub/sub机制向某个通道发送事件,然后订阅者接收这些事件。
例子:
当我们删除在 db 1 中foo键,那么系统会往两个频道推消息,一个是 del 事件频道推 foo 消息,另一个是 foo 频道推 del 消息,两个指令分别等价于:
PUBLISH __keyspace@0__:foo del
PUBLISH __keyevent@0__:del foo
其中往 foo 推送 del 的频道名为 __keyspace@0__:foo,即是 "__keyspace@" + DB_NUMBER + "__:" + KEY_NAME;而 del 的频道名为 "__keyevent@" + DB_NUMBER + "__:" + EVENT_NAME。
2.2 配置
Redis默认下notify-keyspace-events功能处于关闭状态,可以通道命令或者修改配置文件进行打开,notify-keyspace-events可以配置成不同的值,不同的配置具有不同的含义和功能,具体值含义如下:
- K,表示 keyspace 事件,有这个字母表示会往 __keyspace@<db>__ 频道推消息。
- E,表示 keyevent 事件,有这个字母表示会往 __keyevent@<db>__ 频道推消息。
- g,表示一些通用指令事件支持,如 DEL、EXPIRE、RENAME 等等。
- $,表示字符串(String)相关指令的事件支持。
- l,表示列表(List)相关指令事件支持。
- s,表示集合(Set)相关指令事件支持。
- h,哈希(Hash)相关指令事件支持。
- z,有序集(Sorted Set)相关指令事件支持。
- x,过期事件,与 g 中的 EXPIRE 不同的是,g 的 EXPIRE 是指执行 EXPIRE key ttl 这条指令的时候顺便触发的事件,而这里是指那个 key 刚好过期的这个时间点触发的事件。
- e,驱逐事件,一个 key 由于内存上限而被驱逐的时候会触发的事件。
- g$lshzxe 的别名。也就是说 AKE 的意思就代表了所有的事件。
注意:输入的参数中至少要有一个 K 或者 E , 否则的话, 不管其余的参数是什么, 都不会有任何通知被分发。值一定要放在双引号内,如:notify-keyspace-events = “Ex”
根据我们的需求配置notify-keyspace-events = “Ex”,linux下redis的配置文件默认在/etc/redis/redis.conf
2.3 代码中应用
为了方便管理与更新,已经把实例代码放到github上:git@github.com:lisemi/redis-subpub-demo.git