Redis的发布与订阅,有点相似于消息队列,发送者往频道发送消息,频道的订阅者接收消息。java
首先,在本机开启第1个Redis客户端,执行以下命令订阅blog.redis
频道:redis
SUBSCRIBE "blog.redis"
而后,在本机开启第2个Redis客户端,执行相同的命令订阅blog.redis
频道:shell
而后,开启第3个Redis客户端,执行以下命令往blog.redis
频道发送消息:服务器
PUBLISH blog.redis "redis-in-action-01"
查看客户端1和客户端2,分别看到以下信息:设计
3个客户端与频道的关系以下图所示:code
能够经过INFO clients
命令查看链接的客户端数:blog
Redis的SUBSCRIBE
命令用来订阅频道,使用方式以下所示:队列
SUBSCRIBE "blog.redis"
若是是订阅多个频道,可使用以下所示命令:消息队列
SUBSCRIBE "blog.redis" "blog.rocketmq"
Redis将全部频道的订阅关系保存在服务器状态的pubsub_channels
字典里,字典的键是某个被订阅的频道,键对应的值是1个链表,链表里记录了全部订阅这个频道的客户端。io
以上图为例,说明客户端一、客户端2正在订阅频道"blog.redis",客户端三、客户端4正在订阅频道“blog.rocketmq”。
若是此时有1个客户端5,执行了以下命令:
SUBSCRIBE "blog.rocketmq" "blog.java"
那么服务器状态保存的频道订阅关系将变为以下图所示:
Redis的UNSUBSCRIBE
命令用来退订频道,使用方式以下所示:
UNSUBSCRIBE "blog.redis"
若是是退订多个频道,可使用以下所示命令:
UNSUBSCRIBE "blog.redis" "blog.rocketmq"
假设如今服务器状态保存的频道订阅关系以下图所示:
若是此时客户端5,执行了以下命令:
UNSUBSCRIBE "blog.rocketmq" "blog.java"
那么服务器状态保存的频道订阅关系将变为以下图所示:
首先,启动1个Redis客户端,执行以下命令订阅模式“blog.r*”:
PSUBSCRIBE "blog.r*"
而后,启动另1个Redis客户端,执行PUBLISH
命令往频道发送消息:
PUBLISH "blog.redis" "redis-in-action-01" PUBLISH "blog.rocketmq" "rocketmq-in-action-01" PUBLISH "blog.java" "java-in-action-01"
能够看到,第1次启动的客户端能够接收到前2条消息,由于频道"blog.redis"、"blog.rocketmq"匹配模式“blog.r*”:
但频道"blog.java"不匹配该模式,因此最后1次发送的消息,该客户端未接收到。
Redis的PSUBSCRIBE
命令用来订阅模式,使用方式以下所示:
PSUBSCRIBE "blog.r*"
若是是订阅多个模式,可使用以下所示命令:
PSUBSCRIBE "blog.r*" "blog.j?va" "blog.j[ae]va"
Redis将全部模式的订阅关系保存在服务器状态的pubsub_patterns
属性里。
pubsub_patterns
属性是1个链表,链表中的每一个节点是1个pubsub_Pattern
结构,这个结构的pattern
属性记录被订阅的模式,client
属性记录订阅模式的客户端。
以上图为例,说明客户端1正在订阅模式"blog.r*,客户端2正在订阅模式“blog.j?va”。
若是此时有1个客户端3,执行了以下命令:
PSUBSCRIBE "blog.j[ae]va"
那么服务器状态保存的模式订阅关系将变为以下图所示:
Redis的PUNSUBSCRIBE
命令用来退订模式,使用方式以下所示:
PUNSUBSCRIBE "blog.r*"
若是是退订多个模式,可使用以下所示命令:
PUNSUBSCRIBE "blog.j?va" "blog.j[ae]va"
假设如今服务器状态保存的模式订阅关系以下图所示:
若是此时客户端3,执行了以下命令:
PUNSUBSCRIBE "blog.j[ae]va"
那么服务器状态保存的模式订阅关系将变为以下图所示:
若是,服务器状态保存的频道订阅关系以下图所示:
服务器状态保存的模式订阅关系以下图所示:
此时,若是1个Redis客户端执行了如下PUBLISH命令:
PUBLISH blog.redis "redis-in-action-01"
那么,服务器会执行如下2个动做:
也就是说,消息"redis-in-action-01"不只会发送给频道“blog.redis”的订阅者客户端一、客户端2,也会发送给与频道“blog.redis”相匹配的模式“blog.r*”的订阅者客户端5。
可使用Redis的PUBSUB
命令来查看频道或者模式的相关信息。
若是想要查看被订阅的频道信息,可使用命令PUBSUB CHANNELS [pattern]
,其中pattern参数是可选的:
这个命令的实现原理是经过遍历服务器状态保存的pubsub_channels
字典来实现的。
举个具体的例子,若是服务器状态保存的pubsub_channels
字典以下所示:
那么执行命令PUBSUB CHANNELS
的返回结果以下所示:
执行命令PUBSUB CHANNELS r*
的返回结果以下所示:
若是想要查看频道的订阅者数量,可使用命令PUBSUB NUMSUB [channel1 channel2 ... channeln]
。
这个命令的实现原理是经过遍历服务器状态保存的pubsub_channels
字典来实现的,频道对应的订阅者链表的长度就是该频道的订阅者数量。
举个具体的例子,若是服务器状态保存的pubsub_channels
字典以下所示:
那么执行命令PUBSUB NUMSUB blog.redis blog.rocketmq blog.java
的返回结果以下所示:
若是想要查看被订阅模式的数量,可使用命令PUBSUB NUMPAT
。
这个命令的实现原理是返回服务器状态保存的pubsub_patterns
链表的长度。
举个具体的例子,若是服务器状态保存的pubsub_patterns
链表以下所示:
那么执行命令PUBSUB NUMPAT
的返回结果以下所示:
Redis的发布与订阅有点相似于消息队列的发布与订阅,主要包含如下7个命令:
这7个命令的核心都是基于存储在服务器状态的pubsub_channels
字典和pubsub_patterns
链表实现的。
黄健宏 《Redis设计与实现》