Redis:20---常用功能之(发布与订阅)

一、发布与订阅概述

  • Redis提供了基于“发布/订阅”模式的消息机制,此种模式下,消息发布者和订阅者不进行直接通信,发布者客户端向指定的频道(channel)发布消息,订阅该频道的每个客户端都可以收到该消息。

  •  下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:

当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

  • Redis主要提供了发布消息、订阅频道、取消订阅以及按照模式订阅和取消订阅等命令

二、发布消息(publish)

PUBLISH <channel> <message>
  • 当一个客户端执行PUBLISH命令的时候,会将消息message发送给频道channel

  • 例如:下面操作会向channel:sports频道发布一条消息“Tim won the championship”,返回结果为订阅者个数,因为此时没有订阅,所以返回结果为0

publish channel:sports "Tim won the championship"

二、订阅消息(subscribe)

subscribe channel [channel...]
  • 订阅者可以订阅一个或多个频道

  • 注意事项:

    • 客户端在执行订阅命令之后进入了订阅状态,只能接收subscribe、 psubscribe、unsubscribe、punsubscribe的四个命令

    • 新开启的订阅客户端,无法收到该频道之前的消息,因为Redis不会对发布的消息进行持久化

演示案例

  • 下面操作为当前客户端订阅了channel:sports频道:

subscribe channel:sports

 

  • 此时右侧另一个客户端向channel:sports频道发布一条消息,右侧客户端会收到这条消息

publish channel:sports "James lost the championship"

  • 开发提示:和很多专业的消息队列系统(例如Kafka、RocketMQ)相比,Redis的发布订阅略显粗糙,例如无法实现消息堆积和回溯。但胜在足够简单,如果当前场景可以容忍的这些缺点,也不失为一个不错的选择

三、取消订阅(unsubscribe)

unsubscribe [channel [channel ...]]
  • 客户端可以通过unsubscribe命令取消对指定频道的订阅,取消成功后, 不会再收到该频道的发布消息

  • 取消订阅只对本个客户端有效,不会对其他客户端造成影响

  • 例如:

 

四、模式订阅/取消模式订阅(psubscribe、punsubscribe)

psubscribe pattern [pattern...]
punsubscribe [pattern [pattern ...]]
  • psubscribe和punsubscribe是支持glob风格的订阅/取消订阅,称之为“模式订阅”

例如:

  • 下面左侧客户端订阅以it开头的所有频道

psubscribe it*

 

  • 右侧客户端向itformation频道发送一条消息,左侧客户端可以收到这条消息

五、查询订阅

①查询活跃的频道

pubsub channels [pattern]
  • 所谓活跃的频道是指当前频道至少有一个订阅者,其中[pattern]是可以指定具体的模式

  • 例如,下面左侧客户端订阅一个名为“it_redis”的频道,右侧使用pubsub查询,结果会显示出来

  • 当然,我们也可以具体指出查询哪个频道,如果频道不存在会返回空

  • 当有模式订阅时,也可以检测出来

②查看频道订阅数

pubsub numsub [channel ...]
  • 该命令不仅可以检测出是否有活跃的频道,还能检测出频道的订阅数

  • 例如,左侧一个客户端订阅channel:sports频道,右侧客户端查询结果为1

③查看模式订阅数

pubsub numpat
  • 该命令可以查询出当前服务器中有多少个模式订阅

  • 例如,当前所有客户端中只有左侧一个订阅,并且不是模式订阅,所以右侧结果显示为0

  • 现在我们在左侧开启模式订阅,右侧查询结果显示为1

六、发布-订阅的使用场景

  • 聊天室、公告牌、服务之间利用消息解耦都可以使用发布订阅模式

  • 下面以简单的服务解耦进行说明。如下图所示,图中有两套业务:

    • 上面为视频管理系统,负责管理视频信息

    • 下面为视频服务面向客户,用户可以通过各种客户端(手机、浏览器、接口)获取到视频信息

  • 假如视频管理员在视频管理系统中对视频信息进行了变更,希望及时通知给视频服务端,就可以采用发布订阅的模式,发布视频信息变化的消息到指定频道,视频服务订阅这个频道及时更新视频信息,通过这种方式可以有效解决两个业务的耦合性

  • 视频服务订阅video:changes频道如下:

subscribe video:changes
  • 视频管理系统发布消息到video:changes频道如下:

publish video:changes "video1,video3,video5"
  • 当视频服务收到消息,对视频信息进行更新,如下所示:

for video in video1,video3,video5
update {video}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/444301.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis:19---常用功能之(HyperLogLog)

一、HyperLogLog概述HyperLogLog并不是一种新的数据结构&#xff08;实际类型为字符串类型&#xff09;&#xff0c;而是一种基数算法&#xff0c;通过HyperLogLog可以利用极小的内存空间完成独立总数的统计&#xff0c;数据集可以是IP、Email、ID等HyperLogLog提供了3个命令&a…

计算时间差的Oracle函数

Oracle函数可以实现诸多的功能&#xff0c;下面就介绍使用Oracle函数计算时间差的实现方法&#xff0c;如果您对Oracle函数方面感兴趣的话&#xff0c;不妨一看。 两个Date类型字段&#xff1a;START_DATE&#xff0c;END_DATE&#xff0c;计算这两个日期的时间差&#xff08;分…

leetcode181. 超过经理收入的员工(SQL)

Employee 表包含所有员工&#xff0c;他们的经理也属于员工。每个员工都有一个 Id&#xff0c;此外还有一列对应员工的经理的 Id。 ------------------------------ | Id | Name | Salary | ManagerId | ------------------------------ | 1 | Joe | 70000 | 3 |…

UNIX(多线程):01---线程简介及线程限制

一、线程的概念 典型的UNIX进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事。有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻能够做不止一件事,每个线程处理各自独立的任务二、线程的优点 通过为每种事件类型分配单独的处理线程,可以简化处理异步…

UNIX(多线程):13---condition_variable、wait、notify_one、notify_all

条件变量std::condition_variable、wait()、notify_one() 线程A: 等待一个条件满足线程B: 专门往消息队列中放入消息(数据),达到一定条件,通知处于等待中的线程A。std::condition_variable实际上是一个类,是一个和条件相关的一个类,说白了就是等待一个条件达成。这个类是…

leetcode176. 第二高的薪水(SQL)

编写一个 SQL 查询&#xff0c;获取 Employee 表中第二高的薪水&#xff08;Salary&#xff09; 。 ------------ | Id | Salary | ------------ | 1 | 100 | | 2 | 200 | | 3 | 300 | ------------ 例如上述 Employee 表&#xff0c;SQL查询应该返回 200 作为第二…

UNIX(多线程):17---异步任务提供者(Provider) 介绍

std::promise 类概述 Promise 对象可以保存某一类型 T 的值,该值可被 future 对象读取(可能在另外一个线程中),因此 promise 也提供了一种线程同步的手段。在 promise 对象构造时可以和一个共享状态(通常是std::future)相关联,并可以在相关联的共享状态(std::future)上保…

leetcode180. 连续出现的数字(SQL)

编写一个 SQL 查询&#xff0c;查找所有至少连续出现三次的数字。 --------- | Id | Num | --------- | 1 | 1 | | 2 | 1 | | 3 | 1 | | 4 | 2 | | 5 | 1 | | 6 | 2 | | 7 | 2 | --------- 例如&#xff0c;给定上面的 Logs 表&#xff0c; 1 是唯一连续…

UNIX(多线程):18---异步任务提供者(Provider) 介绍(续)

本文主要介绍 std::packaged_task。 std::packaged_task 包装一个可调用的对象,并且允许异步获取该可调用对象产生的结果,从包装可调用对象意义上来讲,std::packaged_task 与 std::function 类似,只不过 std::packaged_task 将其包装的可调用对象的执行结果传递给一个 std:…

leetcode182. 查找重复的电子邮箱(SQL)

编写一个 SQL 查询&#xff0c;查找 Person 表中所有重复的电子邮箱。 示例&#xff1a; ------------- | Id | Email | ------------- | 1 | ab.com | | 2 | cd.com | | 3 | ab.com | ------------- 根据以上输入&#xff0c;你的查询应返回以下结果&#xff1a; ----…

UNIX(多线程):19---Future 类型详解

Future 类型详解 本文主要介绍 std::future,std::shared_future 以及 std::future_error,另外还会介绍 <future> 头文件中的 std::async,std::future_category 函数以及相关枚举类型。 std::future 详解 std::future 概述 前面已经多次提到过 std::future,那么 std::…

UNIX(多线程):20---生产者消费者实例

本文将综合运用 C++11 中的新的基础设施(主要是多线程、锁、条件变量)来阐述一个经典问题——生产者消费者模型,并给出完整的解决方案。 生产者消费者问题是多线程并发中一个非常经典的问题,相信学过操作系统课程的同学都清楚这个问题的根源。本文将就四种情况分析并介绍生产…

leetcode183. 从不订购的客户(SQL)

某网站包含两个表&#xff0c;Customers 表和 Orders 表。编写一个 SQL 查询&#xff0c;找出所有从不订购任何东西的客户。 Customers 表&#xff1a; ----------- | Id | Name | ----------- | 1 | Joe | | 2 | Henry | | 3 | Sam | | 4 | Max | ----------- Or…

UNIX(多线程):21---线程池实现原理

线程池简介: 线程过多会带来调度开销,进而影响缓存局部性和整体性能。 而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用…

leetcode197. 上升的温度(SQL)

给定一个 Weather 表&#xff0c;编写一个 SQL 查询&#xff0c;来查找与之前&#xff08;昨天的&#xff09;日期相比温度更高的所有日期的 Id。 --------------------------------------------- | Id(INT) | RecordDate(DATE) | Temperature(INT) | -----------------------…

UNIX(多线程):22---几种常见的线程池

常见线程池 1、newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。 从构造方法来看,它可以单独执行,也可以与周期线程池结合用。其任务队列是LinkedBlockingQueue,这是个无界的阻塞…

js正则表达式限制文本框只能输入数字,小数点,英文字母

1.文本框只能输入数字代码(小数点也不能输入)<input οnkeyup"this.valuethis.value.replace(/\D/g,)" onafterpaste"this.valuethis.value.replace(/\D/g,)"> 2.只能输入数字,能输小数点. <input οnkeyup"if(isNaN(value))execCommand(und…

UNIX(多线程):23---线程池注意事项和常见问题

使用线程池的注意事项 死锁任何多线程程序都有死锁的风险,最简单的情形是两个线程AB,A持有锁1,请求锁2,B持有锁2,请求锁1。(这种情况在mysql的排他锁也会出现,不会数据库会直接报错提示)。线程池中还有另一种死锁:假设线程池中的所有工作线程都在执行各自任务时被阻塞…

leetcode 178. 分数排名(SQL)

编写一个 SQL 查询来实现分数排名。如果两个分数相同&#xff0c;则两个分数排名&#xff08;Rank&#xff09;相同。请注意&#xff0c;平分后的下一个名次应该是下一个连续的整数值。换句话说&#xff0c;名次之间不应该有“间隔”。 ----------- | Id | Score | ----------…

UNIX(多线程):24---哪些STL容器是线程安全的

在日常C++开发,少不了和STL,多线程打交道,那么在多线程下,哪些容器时线程安全的,那些不是? 好,这里就举一个简单的例子,我们先看看vector容器,相信你能看出一些问题: #include <iostream> #include <string> #include <algorithm> #inclu…