Redis之发布与订阅
欢迎阅读大魔王的睡前私语系列,这是Redis第九篇文章
发布与订阅
Redis的发布订阅功能由PUBISH,SUBSCRIBE,PSUBSCRIBE命令组成。
通过执行SUBSCRIBE命令,客户端可以订阅一个或者多个频道,从而成为这些频道的订阅者(subscriber):每当有其他客户端向被订的频道发送消息时,频道的所有订阅者都会收到这条消息。
除了订阅频道之外,客户端还可以通过执行PSUBSCRIBE命令订阅一个或者多个模式,从而成为这些模式的订阅者:每当有其他客户端向莫格频道发送消息时,消息不仅会发送给这个频道的所有订阅者,还会发送给所有与这个模式相匹配的模式的订阅者。
- 例如,客户端A正在订阅频道“new.it”。
- 客户端B正在订阅频道“new.et”。
- 客户端C和客户端D正在订阅“new.it”频道和"new.et"频道相匹配的模式"new.[ie].t"。
向“new.it"频道发送消息"hello",那么不仅正在订阅”new.it“频道的客户端A会收到雄安熙,客户端C和D也会收到消息,因为这两个客户端正在订阅匹配"new.it"频道的"new.[ie]t"模式。
频道的订阅与退订
当一个客户端执行SUBSCRIBE命令订阅某个或者某些频道时,这个客户端与被订阅频道之间就建立了一种订阅关系。
Redis将所有频道的订阅关系都保存在服务器状态的pubsub_channels字典里面,这个字典的键是某个被订阅的频道,而键的值则是一个链表,链表里面记录了所有订阅这个频道的客户端:
struct redisServer {//保存所有频道的订阅关系dict *pusub_channels;
};
订阅频道
每当客户端执行SUBSCRIBE命令订阅某个或者某些频道时,服务器都会将客户端与被订阅的频道在pubsub_channels字典进行关联。
根据频道频道是否有其他订阅者,关联操作分为两种情况执行:
- 如果频道已经有其他订阅者,那么它在pubsub_channels字典中必定有相应的订阅者链表,程序唯一要做的就是将客户端添加到订阅者链表的末尾。
- 如果频带还未有任务订阅者,那么它必然不存在字典中,程序首先在pubsub_channels字典中为频道创建一个键,并将这个键的值设置为空链表,然后将客户都安添加到链表,成为链表的第一个元素。
退订频道
UNSUBSCRIBE命令的行为和SUBSCRIBE命令的行为正好相反,当一个客户都安退订某个或者某些频道时,服务器将从pubsub_channels中接触客户端与被退订频道之间的关联:
- 程序会根据被退订的名字,在字典中找到频道对应的订阅者链表,然后从订阅者链表中删除退订的客户端信息
- 如果退订客户端之后,频道的订阅者链表变成了空链表,那么说明这个频道已经没有任务订阅者了,程序将从pubsub_channels字典中删除频道对应的键
模式的订阅与退订
服务器将所有频道的订阅关系都保存在服务器状态pubsub_channels属性里面,服务器也将所有模式的订阅关系都保存在服务器状态的pubsub_patterns属性里面:
struct redisServer {//保存所有模式订阅关系list *pubsub_patterns;
};
pubsub_patterns属性是一个链表,链表中的每个节点都包含着一个pubsubPattern结构,这个结构pattern属性记录了被订阅的模式,而client属性则记录了订阅模式的客户端:
typedef struct pubsubPattern {//订阅模式的客户端redisClient *client;//被订阅的模式robj *pattern;
}pubsubPattern;
订阅模式
每当客户端执行PSUBSCRIBE命令订阅某个或者某些模式的时候,服务器会对每个被订阅的模式执行以下两个操作:
- 新建一个pubsubPattern结构,将结构的pattern属性设置为被订阅的模式,client属性设为订阅模式的客户端
- 将pubsubPattern结构添加到pubsub_pattern链表的表尾。
退订模式
模式的退订命令PUNSUBSCRIBE是PSUBSCRIBE命令的反操作:
当一个客户端退订某个或者某些模式的时候,服务器将在pubsub_patterns链表中查找并且删除那些pattern属性为退订模式,并且client属性为执行退订命令的客户端的pubsubPattern结构
发送消息
当一个Redis客户端执行PUBLISH命令将消息message发送给频道channel时候,服务器需要执行以下两个动作:
- 将消息message发送给channel频道的所有订阅者
- 如果有一个或者多个模式pattern与频道channel相匹配,那么将消息message发送给pattern模式的订阅者
将消息发送给频道订阅者
因为服务器状态中的所有pubsub_channel字典记录了所有频道的订阅关系,所以为了将消息发送给channel频道的所有订阅者,PUBLISH命令要做的就是在pubsub_channels字典里面找到频道channel订阅者名单(一个链表,将消息发送给名单上的所有客户端)
例如,执行以下命令:
PUBLISH ”new.it“ "hello"
那么PUBLISH命令将在pubsub_channels字典中查找键”new.it“对应的链表值,并且通过遍历链表将消息"hello"发送给订阅者
将消息发送给模式订阅者
因为服务器状态中的pubsub_patterns链表记录了所有模式的订阅关系,所以为了将消息发送给所有与channel频道相匹配的模式的订阅者,PUBLISH命令要做的就i是遍历整个链表,查找那些channel频道相匹配的模式,并将消息发送给订阅了这些模式的客户端。
小结
服务器状态在pubsub_channels字典中保存了所有频道的订阅关系:
- SUBSCRIBE命令负责将客户端与被订阅的频道关联到这个字典中,而UNSUBSCRIBE命令则负责接触客户端和被退定的频道之间的关联
- 服务器状态在pubsub_patterns链表保存了所有模式的订阅关系:PSUBSCRIBE命令负责将客户端和被订阅的模式记录到这个链表中,而PUNSUBSCRIBE命令则负责溢出客户端与被退订模式在链表中的记录
- PUBLISH命令通过访问pubsub_channels字典来向频道的所有订阅者发送消息,通过访问pubsub_patterns链表来向所有匹配频道的模式的订阅者发送消息
Redis之发布与订阅相关推荐
- 面试被问到Redis实现发布与订阅,手摸手教
简介 Redis发布与发布功能(Pub/Sub)是基于事件座位基本的通信机制,是目前应用比较普遍的通信模型,它的目的主要是解除消息的发布者与订阅者之间的耦合关系. Redis作为消息发布和订阅之间的服 ...
- Redis实现发布与订阅(转)
简介 Redis发布与发布功能(Pub/Sub)是基于事件座位基本的通信机制,是目前应用比较普遍的通信模型,它的目的主要是解除消息的发布者与订阅者之间的耦合关系. Redis作为消息发布和订阅之间的服 ...
- Redis 学习笔记-NoSQL数据库 常用五大数据类型 Redis配置文件介绍 Redis的发布和订阅 Redis_事务_锁机制_秒杀 Redis应用问题解决 分布式锁
1.NoSQL数据库 1.1 NoSQL数据库概述 NoSQL(NosQL = Not Only sQL ),意即"不仅仅是sQL",泛指非关系型的数据库.NoSQL不依赖业务逻辑 ...
- redis的发布和订阅功能
原理 redis的发布和订阅是个比较高深的概念,我一开始接触的时候感觉很茫然,但是后面用了下发现还是简单的.看来还是多需要自己尝试. 其实和消息队列差不多的原理,就是一个发布的频道,所有订阅这个频道的 ...
- Redis——Redis 的发布和订阅
Redis 的发布和订阅 文章目录 Redis 的发布和订阅 1.什么是发布和订阅 2.Redis 的发布和订阅 3.发布订阅命令行实现 1.什么是发布和订阅 Redis 发布订阅 (pub/sub) ...
- redis学习之redis的发布和订阅
目录 什么是发布和订阅 Redis的发布和订阅 1.客户端可以订阅频道如下图 2.当给这个频道发布消息后,消息就会发送给订阅的客户端 发布订阅命令行实现 1.打开一个客户端订阅channel1 2.打 ...
- 【redis】发布与订阅
发布与订阅 Redis的发布与订阅功能由PUBLISH.SUBSCRIBE.PSUBSCRIBE等命令组成.通过执行SUBSCRIBE命令,客户端可以订阅一个或多个频道,从而成为这些频道的订阅者(su ...
- Redis 的发布与订阅
3.Redis 的发布与订阅 3.1.发布与订阅简述 Redis提供了基于"发布/订阅"模式的消息机制.此种模式下,消息发布者和订阅者不进行直接通信,发布者客户端向指定的频道(ch ...
- Redis 进阶 -- 发布与订阅
文章目录 1. 发布与订阅 1.1 PUBLISH:向频道发送消息 1.2 SUBSCRIBE:订阅频道 1.2.1 接收频道消息 1.3 UNSUBSCRIBE:退订频道 1.4 PSUBSCRIB ...
- Redis 笔记系列(十一)——Redis的发布和订阅机制
2019独角兽企业重金招聘Python工程师标准>>> 本文说的redis功能没啥大用处,大家知道有这回事情就好,我一笔带过. Redis的发布订阅 这是什么 进程间的一种消息通信模 ...
最新文章
- Arduino学习笔记1---开发环境搭建
- 粽子也内卷?2021 互联网大厂端午礼盒大盘点
- Java多线程的几种实现方法
- python struct模块的使用
- Linux Kernel系列三:Kernel编译和链接中的linker script语法详解
- 【算法】CRC 循环冗余校验
- atomiclong 初始化_Java并发编程【1.2时代】
- Golang map 三板斧第二式:注意事项
- xtrabackup启动过程中出现的报错
- Android Dialog详解
- Flutter 修改APP名称和logo
- 台式计算机不休眠,台式机如何设置不休眠
- Java常见的加密解密
- linux的各种自带库-lz -lrt -lm -lc都是什么库
- 如何使用IP地址链接数据库
- matlab中的measure,关于matlab中awgn函数中参数作用的测试
- change事件做延迟处理
- android 7.1 去除分屏功能
- 手把手实现andriod应用增量升级
- OMNeT学习之新建工程
热门文章
- swift iOS sceneKit 导入外部dae
- AI边缘计算分析与视频技术,如何助力企业安全生产智能监管?
- 天上掉馅饼 期望dp+状压dp
- 东方不败III游戏修改大师
- 人人视频APP突遭下架:上亿用户慌了
- 汽车前覆盖板高速碰撞实验
- 3d机器学习open3d学习教程3--点云2
- 韩国 kakaotalk web网页版第三方登录示例 kakaotalk网页版
- i.MX6ULL系统移植:Linux移植3 - make xxx_defconfig分析
- 下面linux程序中哪一个是调试器,【单选题】下面Linux程序中哪一个是调试器?A. vi B. gcc C. gdb D. make...