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. Python潮流周刊#2:Rust 让 Python 再次伟大

    这里记录每周值得分享的 Python 及通用技术内容,部分为英文,已在小标题注明.(本期标题取自其中一则分享,不代表全部内容都是该主题,特此声明.) 文章&教程 1.Python修饰器的函数式 ...

  2. L2-001 紧急救援 (25 分)

    1.题目描述: 作为一个城市的应急救援队伍的负责人,你有一张特殊的全国地图.在地图上显示有多个分散的城市和一些连接城市的快速道路.每个城市的救援队数量和每一条连接两个城市的快速道路长度都标在地图上.当 ...

  3. 代码随想录算法训练营Day46 动态规划

    代码随想录算法训练营 代码随想录算法训练营Day46 动态规划| ●  139.单词拆分 关于多重背包,你该了解这些! 背包问题总结篇! 139.单词拆分 题目链接:139.单词拆分 给定一个非空字符 ...

  4. 【LGR-142-Div.4】洛谷入门赛 #13 赛后总结

    A.魔方 目测入门 -,就是需要开long long //1 #include<bits/stdc++.h> typedef long long valueType; int main() ...

  5. 用AI技术实现自动化的社交媒体广告投放,提高广告效果和收益

    目录 1. 引言 2. 技术原理及概念 2.1 基本概念解释 随着社交媒体的普及,广告投放已经成为了广告行业的重要一环.在过去的几年中,社交媒体广告投放的效果和收益都得到了显著提高,但同时也存在着一些 ...

  6. FPGA加速技术:如何提高系统的性能和安全性

    目录 1. 引言 2. 技术原理及概念 2.1 基本概念解释 2.2 技术原理介绍 3. 实现步骤与流程 3.1 准备工作:环境配置与依赖安装 3.2 核心模块实现 3.3 集成与测试 4. 应用示例 ...

  7. 使用MASA Stack+.Net 从零开始搭建IoT平台 第五章 使用时序库存储上行数据

    @ 目录 前言 分析 实施步骤 时序库的安装 解决playload没有时间戳问题 代码编写 测试 总结 前言 我们可以将设备上行数据存储到关系型数据库中,我们需要两张带有时间戳的表(最新数据表 和 历 ...

  8. 2023-06-27:redis中什么是缓存雪崩?该如何解决?

    2023-06-27:redis中什么是缓存雪崩?该如何解决? 答案2023-06-27: 缓存雪崩是指当缓存层承载大量请求并有效保护存储层时,如果缓存层由于某些原因无法提供服务,例如缓存数据大面积失 ...

  9. P2709 小B的询问题解

    本题需要用到莫队算法 关于莫队算法 莫队算法是一种离线算法,适用于序列中统计区间特定的目标的问题. 时间复杂度通常是 \(O(n \sqrt n)\) 或更高. P2709 小B的询问 点击查看原题 ...

  10. fdisk 命令 创建分区 实现扩容

    fdisk 命令 创建分区 实现扩容 Linux fdisk命令简介 Linux fdisk 是一个创建和维护分区表的程序,它兼容 DOS 类型的分区表.BSD 或者 SUN 类型的磁盘列表. 菜单操 ...