Redis系列1:深刻理解高性能Redis的本质

Redis系列2:数据持久化提高可用性

Redis系列3:高可用之主从架构

Redis系列4:高可用之Sentinel(哨兵模式)

Redis系列5:深入分析Cluster 集群模式

追求性能极致:Redis6.0的多线程模型

追求性能极致:客户端缓存带来的革命

Redis系列8:Bitmap实现亿万级数据计算

Redis系列9:Geo 类型赋能亿级地图位置计算

Redis系列10:HyperLogLog实现海量数据基数统计

Redis系列11:内存淘汰策略

Redis系列12:Redis 的事务机制

Redis系列13:分布式锁实现

Redis系列14:使用List实现消息队列

Redis系列15:使用Stream实现消息队列

Redis系列16:聊聊布隆过滤器(原理篇)

Redis系列17:聊聊布隆过滤器(实践篇)

Redis系列18:过期数据的删除策略

Redis系列19:LRU内存淘汰算法分析

Redis系列20:LFU内存淘汰算法分析

Redis系列21:缓存与数据库的数据一致性讨论

1 关于Redis 的 Pub/Sub

Redis的发布订阅(Pub/Sub)模式是一种消息传递机制,它允许在发送者和接收者之间建立松耦合的通信关系。在这种模式中,发送者(发布者)将消息发布到一个指定的频道或模式,而接收者(订阅者)可以订阅一个或多个频道,以便接收发布的消息。

以下是Redis发布订阅模式的主要组件:

发布者(Publisher):发布者是产生并发布消息的实体。它可以将消息发送到指定的频道或模式。

订阅者(Subscriber):订阅者是接收并处理消息的实体。它可以订阅一个或多个频道或模式,以便接收相关的消息。

频道(Channel):频道是发布者和订阅者之间的通信渠道。发布者将消息发送到频道,而订阅者从频道接收消息。

可以看下图,Publisher 和 Subscriber、Channel的关系很清晰:



发布者往 "Channel A" 通道发布消息:Hello World!,消息的所有订阅者就会收到这个消息。

2 使用Pub/Sub实现发布订阅的过程

Redis实现 发布/订阅 一共有两种模式:

  • 使用频道(Channel)进行发布订阅
  • 使用模式(Pattern)进行发布订阅

我们知道,Redis 可以支持多个数据库,每个数据库都有自己的命名空间和数据。通过使用多个数据库,可以实现数据隔离、分区和组织。

但是值得注意的是,这种发布订阅机制与 数据分区空间无关,比如在 db 0 发布消息, 其他区的订阅者都会收到消息。

2.1 通过频道(Channel)进行发布订阅

  • 首先,Subscriber订阅某个Channel,实现对Channel的监听
  • Publisher 对 Channel 这个服务中心媒介发布消息
  • 所有订阅 Channel 的Subscriber接收到消息

接下来我们通过这几个步骤看看具体是怎么实现发布与订阅的过程的。

2.1.1 订阅者订阅频道

SUBSCRIBE命令:订阅者使用SUBSCRIBE命令订阅一个或多个频道。语法为SUBSCRIBE channel [channel ...]。

时间复杂度为O(n) ,n 为订阅的 Channel 数量。

SUBSCRIBE mychannel
Reading messages... (press Ctrl-C to quit)
1) "subscribe" // Message Type
2) "mychannel" // channel
3) (integer) 1

执行完该指令后,订阅者可以使用以下命令操作 Pub/Sub 工作:

  • subscribe:订阅
  • unsubscribe:取消订阅
  • psubscribe:订阅者使用PSUBSCRIBE命令订阅一个或多个模式
  • punsubscribe:订阅者使用PUNSUBSCRIBE命令取消订阅一个或多个模式

我们使用客户端 [subscriber A] 订阅Channel [mychannel] 来接收消息。从上面可以看出响应的信息:

  • "subscribe" :消息类型,枚举是 subscribe、message、unsubscribe
  • "mychannel" :频道的名称
  • 最后的消息内容:不同的消息类型代表不同含义。

进入订阅后的客户端可以收到 3 种枚举类型的消息:

  • subscribe:订阅成功的消息类型,第2个值是订阅成功的频道名称,第3个值是当前客户端订阅的频道数量。(参考我们上面的mychannel消息)
  • message:客户端接收消息的消息类型,第2个值表示产生消息的频道名称,第3个值是消息的内容。
  • unsubscribe:取消订阅的消息类型,第2个值是对应的频道名称,第3个值是当前客户端订阅的频道数量。值为 0 时说明客户端一个订阅的都没有了,退出订阅状态。

2.1.2 发布者发布消息

PUBLISH命令:发布者使用PUBLISH命令将消息发送到指定的频道。语法为 PUBLISH channel message

PUBLISH mychannel "Hello, World!"
(integer) 1

需要注意咱们发布的消息并不会持久化存储下来,所以消息发布之后被某个 Subcriber 订阅到的话,消息生命周期基本就完成了。

2.1.3 订阅者接收消息

如果想要收到上面 发布者发布的消息,我们的客户端首先需要关注了 [mychannel] 频道,才能收到 "Hello, World!" 这条消息。

// 第一步,订阅Channel频道
SUBSCRIBE mychannel
Reading messages... (press Ctrl-C to quit)
1) "subscribe" // 订阅成功
2) "mychannel" // 频道名称
3) (integer) 1 // 订阅频道数量 // 第二步,当Publisher发布消息,Subcriber订阅到的消息如下
1) "message" // 接受到消息
2) "mychannel" // 频道名称
3) "Hello, World!" // 消息内容

2.1.4 退订频道

如果你不想收到某个频道的消息了,你可以取消预订。类似取消朋友圈关注,之后就不会收到推送了。

UNSUBSCRIBE命令:订阅者使用UNSUBSCRIBE命令取消订阅一个或多个频道。语法为 UNSUBSCRIBE channel [channel ...]

UNSUBSCRIBE mychannel

2.2 使用模式(Pattern)匹配实现发布订阅

我们来看看另一种实现发布订阅的方案 ,就是模式匹配的方式,除了直接订阅的客户端之外,还会检查是否有与我们模式相匹配的Channel,如果有,

消息也会发布到对应匹配的频道上,订阅这个Channel的客户端也会收到消息。

我们来试试看效果,订阅匹配模式如下图:

当 Message.Queue.Area1 频道接收到消息之后,除了订阅自身频道的 Actor A 和 Actor B 能收到消息之外。因为频道与模式匹配成功,消息还会发送给订阅 Message.Queue.* 模式的所有人员。

如上面图中的那样,因为使用匹配模式,PUBLISH 消息发布到 Message.Queue.Area2 之外,还会将该 Channel 与匹配模式的Channel进行对比,如果 Channel 与某个模式匹配的话,也将这个消息发布到订阅这个模式的客户端。

所以中红色线条部分,包括Actor C、Actor D、Actor E 都接受到了消息。

2.2.1 订阅模式的相关语法

  • 订阅模式指令:PSUBSCRIBE
PSUBSCRIBE Message.Queue.*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe" // 消息类型:使用模式(Pattern)进行发布订阅
2) "Message.Queue.*"// 匹配的模式
3) (integer) 1 //订阅数
  • 取消模式订阅的指令:PUNSUBSCRIBE
PUNSUBSCRIBE Message.Queue.*
  • 订阅 Message.Queue.Area1 和 Message.Queue.Area2 频道的
# Message.Queue.Area1
SUBSCRIBE Message.Queue.Area1
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "Message.Queue.Area1"
3) (integer) 1 # Message.Queue.Area2
SUBSCRIBE Message.Queue.Area2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "Message.Queue.Area2"
3) (integer) 1
  • Publisher向Message.Queue.Area2发布消息
# 匹配模式的订阅者收到消息
PSUBSCRIBE Message.Queue.*
Reading messages... (press Ctrl-C to quit)
1) "psubscribe"
2) "Message.Queue.*"
3) (integer) 1
# 进入订阅状态,接收到消息
1) "pmessage" # 消息类型
2) "Message.Queue.*" # 模式匹配
3) "Message.Queue.Area2" # 匹配的Channel
4) "Hello World!" # 具体的消息消息内容 # 对应频道的订阅者收到消息
SUBSCRIBE Message.Queue.Area2
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "Message.Queue.Area2"
3) (integer) 1
# 准备接收消息
1) "message"
2) "Message.Queue.Area2"
3) "Hello World!"

因为没有筛重策略,所以如果你既订阅了匹配模式(如 Message.Queue.* ),又订阅了对应的频道(如 Message.Queue.Area2),那么你的客户端会收到两条同样的消息,一条消息类型是message,一条类型是pmessage。

2.3 程序实现

参考官方代码:

# 消息消费代码,监听频道
RShardedTopic topic = redisson.getShardedTopic("myTopic");
int listenerId = topic.addListener(SomeObject.class, new MessageListener<SomeObject>() {
@Override
public void onMessage(String channel, SomeObject message) {
//...
}
}); # 消息生产代码
// in other thread or JVM(发布消息与监听消息要运行在不同的 JVM,因为同一个redisonClinet,无法监听到自己的消息)
RShardedTopic topic = redisson.getShardedTopic("myTopic");
long clientsReceivedMessage = topic.publish(new SomeObject());

3 总结

Redis 实现发布订阅的功能,包括如下指令:

  • subscribe:订阅
  • unsubscribe:取消订阅
  • psubscribe:订阅者使用PSUBSCRIBE命令订阅一个或多个模式
  • punsubscribe:订阅者使用PUNSUBSCRIBE命令取消订阅一个或多个模式
  • publish channel message:向指定的频道channel发送消息message

Redis实现 发布/订阅 一共有两种模式:

  • 使用频道(Channel)进行发布订阅
  • 使用模式(Pattern)进行发布订阅

需要注意的是,当使用Pattern进行发布订阅的时候。如果有消息发布出来,除了订阅该Channel的Client之外,所有订阅了与Channel匹配的模式的Client同样会收到消息。

另外,Redis 发布订阅的消息不会被持久化,所以无历史消息,也不支持 ACK 机制,与之前介绍过的 List 与 Stream 消息队列能力是不同的,大家注意区分,在不同的场景下合理使用。

Redis系列22:Redis 的Pub/Sub能力的更多相关文章

  1. Redis系列(二):Redis的数据类型及命令操作

    原文链接(转载请注明出处):Redis系列(二):Redis的数据类型及命令操作 Redis 中常用命令 Redis 官方的文档是英文版的,当然网上也有大量的中文翻译版,例如:Redis 命令参考.这 ...

  2. Redis系列(一):Redis的简介与安装

    原文链接(转载请注明出处):Redis系列(一):Redis的简介与安装 什么是 Redis Redis 是一个使用ANSI C 编写的开源.支持网络协议.基于内存.可选持久性的键值对数据库,它是一个 ...

  3. Redis系列一 Redis安装

    Redis系列一    Redis安装 1.安装所使用的操作系统为Ubuntu16.04 Redis版本为3.2.9 软件一般下载存放目录为/opt,以下命令操作目录均为/opt root@ubunt ...

  4. redis系列:redis介绍与安装

    前言 这个redis系列的文章将会记录博主学习redis的过程.基本上现在的互联网公司都会用到redis,所以学习这门技术于你于我都是有帮助的. 博主在写这个系列是用的是目前最新版本4.0.10,虚拟 ...

  5. 深入剖析Redis系列: Redis集群模式搭建与原理详解

    前言 在 Redis 3.0 之前,使用 哨兵(sentinel)机制来监控各个节点之间的状态.Redis Cluster 是 Redis 的 分布式解决方案,在 3.0 版本正式推出,有效地解决了 ...

  6. Redis系列之----Redis的两种持久化机制(RDB和AOF)

    Redis的两种持久化机制(RDB和AOF) 什么是持久化    Redis的数据是存储在内存中的,内存中的数据随着服务器的重启或者宕机便会不复存在,在生产环境,服务器宕机更是屡见不鲜,所以,我们希望 ...

  7. 【Redis 系列】redis 学习十六,redis 字典(map) 及其核心编码结构

    redis 是使用 C 语言编写的,但是 C 语言是没有字典这个数据结构的,因此 C 语言自己使用结构体来自定义一个字典结构 typedef struct redisDb src\server.h 中 ...

  8. redis 系列22 复制Replication (下)

    一. 复制环境准备 1.1 主库环境(172.168.18.201) 环境 说明 操作系统版本 CentOS  7.4.1708  IP地址 172.168.18.201 网关Gateway 172. ...

  9. Redis系列(三)-Redis发布订阅及客户端编程

    阅读目录 发布订阅模型 Redis中的发布订阅 客户端编程示例 0.3版本Hredis 发布订阅模型 在应用级其作用是为了减少依赖关系,通常也叫观察者模式.主要是把耦合点单独抽离出来作为第三方,隔离易 ...

  10. redis系列之Redis应用场景

    1 取最新N个数据的操作 比如典型的取你网站的最新文章,通过下面方式,我们可以将最新的5000条评论的ID放在Redis的List集合中,并将超出集合部分从数据库获取 1)使用LPUSH latest ...

随机推荐

  1. pytest在conftest里添加钩子函数进行失败处截图,并绑定到allure报告里

    在conftest里要先定义一个selenium之类的driver. @pytest.hookimpl(tryfirst=True, hookwrapper=True)def pytest_runte ...

  2. Flutter调优--深入探究MediaQuery引起界面Rebuild的原因及解决办法

    前言 我们可以通过MediaQuery.of(context)方法获取到一些设备和系统的相关信息,比如状态栏的高度.当前是否是黑暗模式等等,使用起来相当方便,但是也要注意可能引起的页面rebuild问 ...

  3. Oracle Linux切换uek内核到rhck内核解决ACFS兼容问题

    背景:协助客户做验证,客户使用的是RHEL7.6环境,我这边是OEL7.6环境,开始以为区别不大,结果acfs兼容还是遇到问题,特此记录下. 现象:asmca图形没有acfs相关内容,无法使用acfs ...

  4. Linux下程序时间消耗监控与统计

    良好的计时器可帮助程序开发人员确定程序的性能瓶颈,或对不同算法进行性能比较.但要精确测量程序的运行时间并不容易,因为进程切换.中断.共享的多用户.网络流量.高速缓存访问及转移预测等因素都会对程序计时产 ...

  5. CANoe学习笔记(一):创建第一个仿真工程(基于CAN):点灯

    目录 内容: ①创建两个节点,Switch和Light节点 ②创建两个Panel界面 ③capl代码实现Switch控制Light亮灭 事先准备: 养成良好的习惯,将不同文件放入不同文件夹,创建如下几 ...

  6. CoFiltering:BestPracticesandTechniquesinTextGeneration

    目录 Co-Filtering: Best Practices and Techniques in Text Generation Introduction: Text generation has ...

  7. WPF 入门笔记 - 04 - 数据绑定 - 补充内容:资源基础

    宇宙很大,生活更大,也许以后还有缘相见. --三体 该篇作为[WPF 入门笔记 - 04 - 数据绑定] - Additional Content 章节的补充内容 前言 XAML 资源概述 (WPF ...

  8. Winform 巨好看的控件库推荐:MaterialSkin.2

    MaterialSkin.2 控件包是在 MaterialSkin 及基础上二次开发而来的,在原控件基础上修复了一些Bug,丰富了主题以及动画效果,效果非常好. MaterialSkin.2 现在处于 ...

  9. php屏蔽非正常访问和检测用户登录检测

    <?phpnamespace Manage\Controller;use Common\Controller\DefaultController;class BaseController ext ...

  10. PHP如何获取短网址跳转之前的网址?

    现在有很多的短网址应用,点击就跳转到缩短之前的网址了,那今天我们就来看一下,PHP如何**短网址跳转之前的网址,其实也很简单,就是用php的get_headers 函数,取得Response Head ...