Redis 发布与订阅模式匹配符示例¶
一直以来,
我对 Redis 的订阅与发布功能都有一个误解:
因为 Redis 在文档中总是使用带 *
符号的模式来做示例,
我一直错误地认为 Redis 的模式只能使用 *
符号来做匹配符。
直到前几天,
因为翻译 Redis 订阅与发布功能文档 的缘故,
我看了一下负责对模式进行匹配的 stringmatchlen
函数的 代码 ,
这时才发现,
原来 Redis 的模式名中不仅可以包含 *
符号,
还可以使用其他 glob
风格的匹配符,
比如 ?
和 [...]
。
Tip
glob
程序的文档可以通过 man 7 glob
命令查看,
其中的 Wildcard Matching 小节记录了各个匹配符的用法。
因为 Redis 的文档里并没有对除 *
符号之外的其他匹配符进行介绍,
所以我想如果有一篇专门介绍 Redis 发布与订阅模式的文章应该也会对其他人有帮助,
这就是本文的写作目的。
在接下来的小节里, 每个小节将介绍一种 Redis 模式可以使用的匹配符。
*
匹配符¶
*
匹配符可以匹配任意的字符串,
包括空字符串。
比如说,
模式 *news
可以匹配 sport news
、 breaking news
:
redis 127.0.0.1:6379> PSUBSCRIBE *news
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "*news"
3) (integer) 1
1) "pmessage"
2) "*news"
3) "sport news"
4) "hello world from sport news"
1) "pmessage"
2) "*news"
3) "breaking news"
4) "hello world from breaking news"
或者正好是字符串 news
:
1) "pmessage"
2) "*news"
3) "news"
4) "hello world"
等等。
?
匹配符¶
?
匹配符可以匹配任意一个字符。
比如说,
Re?is
可以匹配 Redis
、 ReDis
、 Regis
、 Re-is
等等。
以下是一个订阅 Re?is
模式的客户端:
redis 127.0.0.1:6379> PSUBSCRIBE Re?is
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "Re?is"
3) (integer) 1
当有信息发送到 Redis
频道的时候,
它将接收到以下信息:
1) "pmessage"
2) "Re?is"
3) "Redis"
4) "hello from channel Redis"
另外,
因为 ReDis
和 Re-is
等频道也和 Re?is
模式匹配,
所以当有信息发送到这些频道的时候,
订阅 Re?is
模式的客户端也会收到信息:
1) "pmessage"
2) "Re?is"
3) "ReDis"
4) "hello from channel ReDis"
1) "pmessage"
2) "Re?is"
3) "Re-is"
4) "hello from channel Re-is"
[...]
匹配符¶
[...]
匹配符可以匹配给定范围内的单个字符,
其中,
[
和 ]
包围的内容指定了这个字符可能的值。
比如说,
如果我们想匹配 Redis
、 Tedis
和 Uedis
三个频道的信息,
那么可以订阅模式 [RTU]edis
:
redis 127.0.0.1:6379> PSUBSCRIBE [RTU]edis
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "[RTU]edis"
3) (integer) 1
当有信息发送给 Redis
、 Tedis
或 Uedis
中的任意一个时,
订阅客户端都会收到信息:
1) "pmessage"
2) "[RTU]edis"
3) "Redis"
4) "hello from Redis"
1) "pmessage"
2) "[RTU]edis"
3) "Tedis"
4) "hello from Tedis"
1) "pmessage"
2) "[RTU]edis"
3) "Uedis"
4) "hello from Uedis"
和 glob
程序一样,
Redis 的 [...]
匹配符里面也可以使用 -
符号(横杠)来指定范围。
比如说,
要匹配频道 iPhone4
、 iPhone5
和 iPhone6
,
可以订阅模式 iPhone[4-6]
:
redis 127.0.0.1:6379> PSUBSCRIBE iPhone[4-6]
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "iPhone[4-6]"
3) (integer) 1
1) "pmessage"
2) "iPhone[4-6]"
3) "iPhone4"
4) "..."
1) "pmessage"
2) "iPhone[4-6]"
3) "iPhone5"
4) "..."
1) "pmessage"
2) "iPhone[4-6]"
3) "iPhone6"
4) "..."
另外,
要匹配 Aedis
、 Bedis
、 Cedis
一直到 Zedis
频道,
可以订阅 [A-Z]edis
模式:
redis 127.0.0.1:6379> PSUBSCRIBE [A-Z]edis
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "[A-Z]edis"
3) (integer) 1
1) "pmessage"
2) "[A-Z]edis"
3) "Aedis"
4) "..."
1) "pmessage"
2) "[A-Z]edis"
3) "Redis"
4) "..."
1) "pmessage"
2) "[A-Z]edis"
3) "Zedis"
4) "..."
Note
因为 Redis 的 SUBSCRIBE 命令 可以同时订阅多个频道,
所以实际上使用 -
符号来指定范围并不是十分必要的。
比如说,
命令 PSUBSCRIBE iPhone[4-6]
和命令 SUBSCRIBE iPhone4 iPhone5 iPhone6
的效果是一样的,
它们之间的唯一不同之处是前者订阅的是模式,
而后者订阅的是频道。
从目前的频道和模式的实现来看, 使用频道的效率要比模式高(具体请参考《Redis 设计与实现》的《发布与订阅》章节), 因此, 如果可以的话, 应该尽量使用频道而不是模式。
任意组合多个匹配符¶
上面介绍了 *
、 ?
和 [...]
三个匹配符,
要进一步扩大模式的匹配能力,
可以组合使用多个匹配符:
Redis 允许一个模式中包含多个匹配符,
并且每个匹配符的数量没有限制。
比如说,
模式 [ig]Phone*
可以匹配 iPhone
、 gPhone
、 iPhone news
、 gPhone 7
等任意频道:
redis 127.0.0.1:6379> PSUBSCRIBE [ig]Phone*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "[ig]Phone*"
3) (integer) 1
1) "pmessage"
2) "[ig]Phone*"
3) "iPhone"
4) "..."
1) "pmessage"
2) "[ig]Phone*"
3) "gPhone"
4) "..."
1) "pmessage"
2) "[ig]Phone*"
3) "iPhone news"
4) "..."
1) "pmessage"
2) "[ig]Phone*"
3) "gPhone 7"
4) "..."
而模式 *news*
则可以匹配任何包含 news
这一字符串的频道,
比如 news
、 release news of Redis
、 lastes news
,
诸如此类:
redis 127.0.0.1:6379> PSUBSCRIBE *news*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "*news*"
3) (integer) 1
1) "pmessage"
2) "*news*"
3) "news"
4) "..."
1) "pmessage"
2) "*news*"
3) "release news of Redis"
4) "..."
1) "pmessage"
2) "*news*"
3) "lastes news"
4) "..."
总结¶
以上就是本文的全部内容了。
本文对 Redis PSUBSCRIBE 命令 支持的各个匹配符进行了简单的介绍, 希望各位可以从这些简单的例子中获得启发, 创作出更多更强大的模式, 并将它们应用到程序中去。