Redis系列(八):发布与订阅
Redis的发布与订阅,有点类似于消息队列,发送者往频道发送消息,频道的订阅者接收消息。
1. 发布与订阅示例
首先,在本机开启第1个Redis客户端,执行如下命令订阅blog.redis
频道:
SUBSCRIBE "blog.redis"
然后,在本机开启第2个Redis客户端,执行相同的命令订阅blog.redis
频道:
然后,开启第3个Redis客户端,执行如下命令往blog.redis
频道发送消息:
PUBLISH blog.redis "redis-in-action-01"
查看客户端1和客户端2,分别看到如下信息:
3个客户端与频道的关系如下图所示:
可以通过INFO clients
命令查看连接的客户端数:
2. 订阅/退订频道
2.1 订阅频道
Redis的SUBSCRIBE
命令用来订阅频道,使用方式如下所示:
SUBSCRIBE "blog.redis"
如果是订阅多个频道,可以使用如下所示命令:
SUBSCRIBE "blog.redis" "blog.rocketmq"
Redis将所有频道的订阅关系保存在服务器状态的pubsub_channels
字典里,字典的键是某个被订阅的频道,键对应的值是1个链表,链表里记录了所有订阅这个频道的客户端。
以上图为例,说明客户端1、客户端2正在订阅频道"blog.redis",客户端3、客户端4正在订阅频道“blog.rocketmq”。
如果此时有1个客户端5,执行了如下命令:
SUBSCRIBE "blog.rocketmq" "blog.java"
那么服务器状态保存的频道订阅关系将变为如下图所示:
2.2 退订频道
Redis的UNSUBSCRIBE
命令用来退订频道,使用方式如下所示:
UNSUBSCRIBE "blog.redis"
如果是退订多个频道,可以使用如下所示命令:
UNSUBSCRIBE "blog.redis" "blog.rocketmq"
假设现在服务器状态保存的频道订阅关系如下图所示:
如果此时客户端5,执行了如下命令:
UNSUBSCRIBE "blog.rocketmq" "blog.java"
那么服务器状态保存的频道订阅关系将变为如下图所示:
3. 订阅/退订模式
3.1 示例
首先,启动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次发送的消息,该客户端未接收到。
3.2 订阅模式
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"
那么服务器状态保存的模式订阅关系将变为如下图所示:
3.3 退订模式
Redis的PUNSUBSCRIBE
命令用来退订模式,使用方式如下所示:
PUNSUBSCRIBE "blog.r*"
如果是退订多个模式,可以使用如下所示命令:
PUNSUBSCRIBE "blog.j?va" "blog.j[ae]va"
假设现在服务器状态保存的模式订阅关系如下图所示:
如果此时客户端3,执行了如下命令:
PUNSUBSCRIBE "blog.j[ae]va"
那么服务器状态保存的模式订阅关系将变为如下图所示:
4. 发送消息
如果,服务器状态保存的频道订阅关系如下图所示:
服务器状态保存的模式订阅关系如下图所示:
此时,如果1个Redis客户端执行了以下PUBLISH命令:
PUBLISH blog.redis "redis-in-action-01"
那么,服务器会执行以下2个动作:
- 将消息"redis-in-action-01"发送给频道“blog.redis”的所有订阅者
- 将消息"redis-in-action-01"发送给与频道“blog.redis”相匹配模式的订阅者
也就是说,消息"redis-in-action-01"不仅会发送给频道“blog.redis”的订阅者客户端1、客户端2,也会发送给与频道“blog.redis”相匹配的模式“blog.r*”的订阅者客户端5。
5. 查看订阅信息
可以使用Redis的PUBSUB
命令来查看频道或者模式的相关信息。
5.1 查看被订阅的频道
如果想要查看被订阅的频道信息,可以使用命令PUBSUB CHANNELS [pattern]
,其中pattern参数是可选的:
- 如果不指定pattern参数,返回服务器当前被订阅的所有频道
- 如果指定pattern参数,返回服务器被订阅的频道中与pattern模式相匹配的频道
这个命令的实现原理是通过遍历服务器状态保存的pubsub_channels
字典来实现的。
举个具体的例子,如果服务器状态保存的pubsub_channels
字典如下所示:
那么执行命令PUBSUB CHANNELS
的返回结果如下所示:
执行命令PUBSUB CHANNELS r*
的返回结果如下所示:
5.2 查看频道的订阅者数量
如果想要查看频道的订阅者数量,可以使用命令PUBSUB NUMSUB [channel1 channel2 ... channeln]
。
这个命令的实现原理是通过遍历服务器状态保存的pubsub_channels
字典来实现的,频道对应的订阅者链表的长度就是该频道的订阅者数量。
举个具体的例子,如果服务器状态保存的pubsub_channels
字典如下所示:
那么执行命令PUBSUB NUMSUB blog.redis blog.rocketmq blog.java
的返回结果如下所示:
5.3 查看被订阅模式的数量
如果想要查看被订阅模式的数量,可以使用命令PUBSUB NUMPAT
。
这个命令的实现原理是返回服务器状态保存的pubsub_patterns
链表的长度。
举个具体的例子,如果服务器状态保存的pubsub_patterns
链表如下所示:
那么执行命令PUBSUB NUMPAT
的返回结果如下所示:
6. 总结
Redis的发布与订阅有点类似于消息队列的发布与订阅,主要包含以下7个命令:
- SUBSCRIBE
- UNSUBSCRIBE
- PSUBSCRIBE
- PUNSUBSCRIBE
- PUBSUB CHANNELS
- PUBSUB NUMSUB
- PUBSUB NUMPAT
这7个命令的核心都是基于存储在服务器状态的pubsub_channels
字典和pubsub_patterns
链表实现的。
7. 参考
黄健宏 《Redis设计与实现》
Redis系列(八):发布与订阅的更多相关文章
- Redis中的发布与订阅
redis中实现发布与订阅相对于zookeeper非常简单.直接使用publish和subscribe就行. subscrible news; 订阅news这个channel publish news ...
- Redis的消息发布和订阅
Redis的消息发布和订阅 Author:SimpleWu GitHub-redis 什么是消息发布和订阅? Redis 发布订阅(pub/sub)是一种进程间的消息通信模式: 发送者(pub)发送消 ...
- redis 笔记06 发布与订阅、事务、慢查询日志、监视器
发布与订阅 1. 服务器状态在pubsub_channels字典保存了所有频道的订阅关系:SUBSCRIBE命令负责将客户端和被订阅的频道关联到这个字典里面,而UNSUBSCRIBE命令则负责 解除客 ...
- Redis消息之发布与订阅
"发布/订阅"可以实现进程间的消息传递 发布的消息不会持久化,只能收到订阅后的消息,执行subscribe命令后客户端会进入"订阅"状态,处于此状态下的客户端不 ...
- redis 事务 及发布于订阅功能
事务: Redis事务可以一次执行多个命令,事务具有以下特征: 1.隔离操作:事务中的所有命令都会序列化.按顺序地执行,不会被其他命令打扰. 2.原子操作:事务中的命令要么全部被执行,要么全部都不执行 ...
- .NetCore使用Redis,StackExchange.Redis队列,发布与订阅,分布式锁的简单使用
环境:之前一直是使用serverStack.Redis的客服端,今天来使用一下StackExchange.Redis(个人感觉更加的人性化一些,也是免费的,性能也不会差太多),版本为StackExch ...
- Redis系列(三)—— 订阅/发布
Redis 订阅/发布 参考:http://www.cnblogs.com/mushroom/p/4470006.html,http://www.tuicool.com/articles/ABry2a ...
- Redis系列八:redis主从复制和哨兵
一.Redis主从复制 主从复制:主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性 1. 主从复制的相关操作 a,配置主从复制方式一.新增redis6380.conf, ...
- redis 实现消息发布和订阅
1,打开二个客户端机器 一个用于发布,一个用于接受 2,发布一个channel1 3,用另外一个客户端收听上面的客户端 4,当再次在发布的redis客户端 发布一个消息 其他所有订阅的客户端会自动收 ...
随机推荐
- 面试题: SpringBoot 的自动配置原理
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 3.Spring Boot 的自动配置原理 package com.mmall; import org. ...
- Ftrace的部分使用方法
ftrace主要是用于调试linux kernel调度相关的一个工具,也可用于分析部分kernel性能问题. 相关ftrace的介绍可以参考:kernel/msm-4.9/Documentation/ ...
- Java实现 LeetCode 453 最小移动次数使数组元素相等
453. 最小移动次数使数组元素相等 给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数.每次移动可以使 n - 1 个元素增加 1. 示例: 输入: [1,2,3] 输出: 3 ...
- Java实现 LeetCode70 爬楼梯
70. 爬楼梯 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. 示例 1: 输入: 2 输出: ...
- 使用Python爬取网页的相关内容(图片,文字,链接等等)
代码解释的很详细了,有不明白的欢迎评论 ~~~滑稽 import requests from bs4 import BeautifulSoup # #获取图片 输入网址 req=requests.ge ...
- Java实现字符串的包含
1 问题描述 给定一长字符串A和一短字符串B.请问,如何最快地判断出短字符串B中的所有字符是否都在长字符串A中?请编写一个判断函数实现此功能. 为简单起见,假设输入的字符串只包含小写英文字母.下面举几 ...
- Java实现第十届蓝桥杯质数
试题 D: 质数 本题总分:10 分 [问题描述] 我们知道第一个质数是 2.第二个质数是 3.第三个质数是 5--请你计算 第 2019 个质数是多少? [答案提交] 这是一道结果填空的题,你只需要 ...
- java实现第五届蓝桥杯幂一矩阵
幂一矩阵 天才少年的邻居 atm 最近学习了线性代数相关的理论,他对"矩阵"这个概念特别感兴趣.矩阵中有个概念叫做幂零矩阵.对于一个方阵 M ,如果存在一个正整数 k 满足 M^k ...
- 【图机器学习】cs224w Lecture 16 - 图神经网络的局限性
目录 Capturing Graph Structure Graph Isomorphism Network Vulnerability to Noise 转自本人:https://blog.csdn ...
- js循环练习
var a=1; while(a>0){ var b=prompt('input number'); if(b>a){ alert('big'); } else if(b<a){ a ...