Redis 发布/订阅模式与消息队列

news2024/12/16 12:37:28

目录

      • 1. Redis 发布/订阅机制
        • 1.1 基本概念与实现
        • 1.2 C++ 代码实现
          • 1.2.1 安装 hiredis
          • 1.2.2 发布者(Publisher)
          • 1.2.3 订阅者(Subscriber)
        • 1.3 发布/订阅应用场景
        • 1.4 高级特性与优化
      • 2. 使用 Redis 实现简单的消息队列
        • 2.1 基本概念
        • 2.2 C++ 代码实现
          • 2.2.1 生产者(Producer)
          • 2.2.2 消费者(Consumer)
        • 2.3 消息队列应用场景
        • 2.4 可靠性与持久性保障
      • 总结

Redis 提供了强大的消息传递机制,其中**发布/订阅(Pub/Sub)消息队列(Message Queue)**是实现实时消息传递和任务调度的常用方式。这两种机制广泛应用于实时通知系统、事件驱动架构、日志收集和任务队列等场景。本文将深入探讨 Redis 的这两种机制,并结合 C++ 代码进行详细实现。


1. Redis 发布/订阅机制

1.1 基本概念与实现

概念
Redis 的发布/订阅模式通过频道(Channel)来传递消息。生产者(发布者)将消息发布到一个或多个频道,消费者(订阅者)则订阅相应的频道以接收消息。发布者与订阅者之间解耦,发布者无需关心订阅者,订阅者也无需关心发布者。

1.2 C++ 代码实现

要在 C++ 中实现 Redis 发布/订阅机制,可以使用 hiredis 库,它提供了对 Redis 的 C 语言 API 支持。

1.2.1 安装 hiredis

首先,确保已安装 hiredis 库。可以通过以下命令在 Linux 上安装:

sudo apt-get install libhiredis-dev
1.2.2 发布者(Publisher)

发布者使用 PUBLISH 命令将消息发送到指定频道。以下是 C++ 示例代码:

#include <iostream>
#include <hiredis/hiredis.h>

int main() {
    // 连接到 Redis 服务器
    redisContext *c = redisConnect("127.0.0.1", 6379);
    if (c == NULL || c->err) {
        std::cerr << "Connection error: " << (c ? c->errstr : "can't allocate redis context") << std::endl;
        return 1;
    }

    // 发布消息
    const char *channel = "news";
    const char *message = "Redis 发布/订阅模式学习";

    redisReply *reply = (redisReply *)redisCommand(c, "PUBLISH %s %s", channel, message);
    std::cout << "发布消息到频道 '" << channel << "': " << message << std::endl;

    // 释放资源
    freeReplyObject(reply);
    redisFree(c);

    return 0;
}

说明
这段代码连接到 Redis 服务器,并通过 PUBLISH 命令将消息 "Redis 发布/订阅模式学习" 发布到 news 频道。

1.2.3 订阅者(Subscriber)

订阅者使用 SUBSCRIBE 命令订阅一个或多个频道,并进入“订阅模式”,等待接收来自频道的消息。以下是订阅者的 C++ 实现代码:

#include <iostream>
#include <hiredis/hiredis.h>

void subscribeCallback(redisContext *c, void *reply, void *privdata) {
    redisReply *r = (redisReply *)reply;
    if (r->type == REDIS_REPLY_ARRAY && r->elements == 3) {
        std::cout << "收到消息: " << r->element[2]->str << std::endl;
    }
}

int main() {
    // 连接到 Redis 服务器
    redisContext *c = redisConnect("127.0.0.1", 6379);
    if (c == NULL || c->err) {
        std::cerr << "Connection error: " << (c ? c->errstr : "can't allocate redis context") << std::endl;
        return 1;
    }

    // 订阅频道
    const char *channel = "news";
    redisReply *reply = (redisReply *)redisCommand(c, "SUBSCRIBE %s", channel);
    std::cout << "已订阅频道: " << channel << std::endl;

    // 进入订阅模式,接收消息
    while (true) {
        redisGetReply(c, (void **)&reply);
        subscribeCallback(c, reply, nullptr);
        freeReplyObject(reply);
    }

    redisFree(c);

    return 0;
}

说明
这段代码通过 SUBSCRIBE 命令订阅 news 频道,进入“订阅模式”,并通过 subscribeCallback 函数实时处理接收到的消息。

1.3 发布/订阅应用场景
  • 实时通知系统:如消息推送、公告发布、实时聊天。
  • 事件驱动架构:微服务或模块通过订阅感兴趣的事件,实时响应其他服务的变化。
  • 日志收集:通过订阅日志频道,将日志数据实时发送至日志分析系统。
1.4 高级特性与优化
  • 模式匹配订阅(PSUBSCRIBE):支持使用通配符订阅多个频道,例如,订阅所有以 news: 开头的频道。
  • 性能优化
    • 连接池管理:使用连接池管理 Redis 客户端连接,避免每次订阅时都创建新的连接。
    • 分布式发布/订阅:通过 Redis 分布式部署,支持高并发发布/订阅。

2. 使用 Redis 实现简单的消息队列

2.1 基本概念

Redis 的 List 数据结构非常适合用于实现消息队列。常用的命令包括:

  • LPUSH:将消息推入队列。
  • RPUSH:将消息推入队列的另一端。
  • BRPOP:从队列的另一端阻塞地弹出消息。
2.2 C++ 代码实现
2.2.1 生产者(Producer)

生产者将消息推入队列。以下是 C++ 示例代码:

#include <iostream>
#include <hiredis/hiredis.h>

int main() {
    // 连接到 Redis 服务器
    redisContext *c = redisConnect("127.0.0.1", 6379);
    if (c == NULL || c->err) {
        std::cerr << "Connection error: " << (c ? c->errstr : "can't allocate redis context") << std::endl;
        return 1;
    }

    // 将消息推送到队列
    const char *queue = "task_queue";
    redisReply *reply = (redisReply *)redisCommand(c, "LPUSH %s %s", queue, "Task 1");
    std::cout << "任务 'Task 1' 已加入队列" << std::endl;

    // 释放资源
    freeReplyObject(reply);
    redisFree(c);

    return 0;
}

说明
这段代码将任务 "Task 1" 推入队列 task_queue,作为生产者的一部分。

2.2.2 消费者(Consumer)

消费者使用 BRPOP 命令从队列中阻塞地获取消息。以下是消费者的 C++ 示例代码:

#include <iostream>
#include <hiredis/hiredis.h>

int main() {
    // 连接到 Redis 服务器
    redisContext *c = redisConnect("127.0.0.1", 6379);
    if (c == NULL || c->err) {
        std::cerr << "Connection error: " << (c ? c->errstr : "can't allocate redis context") << std::endl;
        return 1;
    }

    // 阻塞地从队列获取任务
    const char *queue = "task_queue";
    redisReply *reply = (redisReply *)redisCommand(c, "BRPOP %s 0", queue);
    if (reply->type == REDIS_REPLY_ARRAY && reply->elements == 2) {
        std::cout << "处理任务: " << reply->element[1]->str << std::endl;
    }

    // 释放资源
    freeReplyObject(reply);
    redisFree(c);

    return 0;
}

说明
消费者通过 BRPOP 命令从队列 task_queue 阻塞地弹出任务,并进行处理。

2.3 消息队列应用场景
  • 任务队列:多个生产者将任务推送到 Redis 队列,多个消费者从队列中消费任务,适用于分布式任务调度和定时任务。
  • 异步处理:例如异步任务(如邮件发送、图片处理等)通过队列推送,消费者进行异步处理,避免阻塞主线程。
2.4 可靠性与持久性保障
  • 消息持久化

:确保 Redis 配置为持久化模式,以防止队列中的数据丢失。

  • 消息确认机制:在分布式环境下,采用消费者确认消息机制,防止消息丢失。

总结

Redis 的发布/订阅机制与消息队列功能在多个应用场景中非常有用,无论是实时通知系统还是任务调度,都能够提供高效且可靠的支持。在 C++ 中,通过 hiredis 库,我们能够轻松实现 Redis 发布/订阅和消息队列的功能。


参考:
0voice · GitHub

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

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

相关文章

使用webrtc-streamer查看实时监控

摄像头配置&#xff08;海康摄像头为例&#xff09; 摄像头视频编码应改成H264格式 webrtc-streamer下载 webrtc-streamer下载地址 下载后解压出来双击运行&#xff0c;端口默认8000 VUE2项目引入文件 在项目静态文件“public”中需引入两个js文件“webrtcstreamer.js”与“…

L1-3流量分析

1. 初步分析 数据包下载 流量分析基础篇 使用科来网络分析系统&#xff0c;打开L1-3.pcapng数据包&#xff0c;查看数据包中ssh的协议占的比例较大。 2. 通过分析数据包L1-3&#xff0c;找出黑客的IP地址&#xff0c;并将黑客的IP地址作为FLAG(形式:[IP地址)提交; 获取的fl…

【经典】制造供应链四类策略(MTS、MTO、ATO、ETO)细说

关注作者 制造供应链的牛鞭问题与复杂问题主要是从两个方面解决&#xff0c;一是同步化供应链消减从需求到供应的放大效应&#xff0c;二是供应链细分&#xff0c;针对不同的客户、不同的需求供应的匹配策略来应对复杂性&#xff0c;更好的满足客户并以最低的总成本来实现。 对…

前端成长之路:CSS盒子模型

盒子模型是页面布局的核心&#xff0c;通过盒子模型才能更好的进行页面布局。 网页布局的本质 网页布局的核心本质其实是&#xff1a;HTML网页元素就是一个个的盒子box&#xff0c;通过CSS可以设置好盒子的样式&#xff0c;和盒子需要摆放的位置&#xff1b;简单说来就是通过…

LeetCode刷题 -- 字符串

目录 最长公共前缀题目解析算法原理代码 最长回文子串题目解析算法原理代码 二进制求和题目解析算法原理代码 字符串相乘题目解析算法原理代码 最长公共前缀 题目链接 题目解析 只需找出字符串中的公共的最长字符串即可 算法原理 1.法一&#xff1a;两两字符串比较&#xff0c;…

4G模块详解

在之前的教程中&#xff0c;无线通信技术我们学习了蓝牙和 WiFi&#xff0c;今天我们要来学习 4G。 4G 模块在距离上有个突破&#xff0c;它不像蓝牙短距离&#xff0c;也不像 WiFi 只能在局域网&#xff0c;4G 模块可使用户无论在哪&#xff0c;只要有 4G 网络信号覆盖&#…

uni-app实现小程序、H5图片轮播预览、双指缩放、双击放大、单击还原、滑动切换功能

前言 这次的标题有点长&#xff0c;主要是想要表述的功能点有点多&#xff1b; 简单做一下需求描述 产品要求在商品详情页的头部轮播图部分&#xff0c;可以单击预览大图&#xff0c;同时在预览界面可以双指放大缩小图片并且可以移动查看图片&#xff0c;双击放大&#xff0…

数据地图怎么做?推荐这款数据可视化地图生成器

在数字化与信息化高速发展的今天&#xff0c;企业迎来了前所未有的发展机遇&#xff0c;规模迅速扩张&#xff0c;市场版图不断延伸。然而&#xff0c;伴随着这种快速的发展&#xff0c;一个不容忽视的问题逐渐浮出水面——如何精准高效地掌握分布在各地的分公司、业务点乃至整…

hive—常用的日期函数

目录 1、current_date 当前日期 2、now() 或 current_timestamp() 当前时间 3、datediff(endDate, startDate) 计算日期相差天数 4、months_between(endDate, startDate) 日期相差月数 5、date_add(startDate, numDays) 日期加N天 6、date_sub(startDate, numDays) 日期减…

【原生js案例】如何让你的网页实现图片的按需加载

按需加载&#xff0c;这个词应该都不陌生了。我用到你的时候&#xff0c;你才出现就可以了。对于一个很多图片的网站&#xff0c;按需加载图片是优化网站性能的一个关键点。减少无效的http请求&#xff0c;提升网站加载速度。 感兴趣的可以关注下我的系列课程【webApp之h5端实…

大模型运用-Prompt Engineering(提示工程)

什么是提示工程 提示工程 提示工程也叫指令工程&#xff0c;涉及到如何设计、优化和管理这些Prompt&#xff0c;以确保AI模型能够准确、高效地执行用户的指令&#xff0c;如&#xff1a;讲个笑话、java写个排序算法等 使用目的 1.获得具体问题的具体结果。&#xff08;如&…

相位小数偏差(UPD)估计基本原理

PPP中的一个关键性难题在于非差模糊度固定&#xff0c;成功固定非差模糊度可以使 PPP 的收敛速度和定位精度得到显著提升 。 相位小数偏差 (UPD) 是致使相位模糊度失去整数特性的主要因素&#xff0c;精确估计并校正 UPD 是实现非差模糊度固定的重要前提&#xff0c;也是实现…

ES倒排索引实现? ES 索引文档过程?ES并发下读写一致?

ES倒排索引实现&#xff0c; ES 索引文档过程&#xff0c;ES并发下读写一致 一、Elasticsearch的基本概念二、Elasticsearch的工作原理简述三、Elasticsearch的应用场景四、面试问题问题1&#xff1a;Elasticsearch中的分片和副本是如何工作的&#xff1f;分片和副本的大小和数…

【h5py】 提取mat文件中的HDF5格式的数据

h5py 提取mat文件中的HDF5格式的数据 使用纯Python查看数据配合Matlab后&#xff0c;使用Python查看数据 一、使用纯Python查看文件数据内容 原理&#xff1a;当HDF5存储的是struct类型数据&#xff0c;解析时要像一棵树&#xff0c;我们需要逐层次的去解析&#xff0c;直到…

【数据分享】2013-2023年我国省市县三级的逐年CO数据(免费获取\excel\shp格式)

空气质量数据是在我们日常研究中经常使用的数据&#xff01;之前我们给大家分享了2000-2023年的省市县三级的逐年PM2.5数据、2000-2023年的省市县三级的逐年PM10数据、2013-2023年的省市县三级的逐年SO2数据、2000-2023年省市县三级的逐年O3数据和2008-2023年我国省市县三级的逐…

《九重紫》逐集分析鉴赏第一集(下)

主标题&#xff1a;《九重紫》一起追剧吧 副标题&#xff1a;《九重紫》逐集分析鉴赏第一集&#xff08;下&#xff09;/《九重紫》逐集分析鉴赏1 接上回分解&#xff0c;窦昭和宋墨都安置城外万佛寺 交谈没一会儿&#xff0c;天还未亮&#xff0c;兵临寺下 记住这个人&…

Summarizing and Understanding Large Graphs

Summarizing and Understanding Large Graphs【总结和理解大规模图】 ☆ 研究背景 大规模图的理解和可视化是一个重要的开放性问题现有的社区发现和聚类方法无法很好地总结图的特征需要一种能够发现和描述图中重要结构的方法 ★ 成果简介 提出了VoG(Vocabulary-based summar…

人工智能系统

介绍人工智能 的基础书 点击这里 1.1 深度学习的历史&#xff0c;现状与发展 本章将介绍深度学习的由来&#xff0c;现状和趋势&#xff0c;让读者能够了解人工智能系统之上的深度学习负载的由来与趋势&#xff0c;为后面理解深度学习系统的设计和权衡形成初步的基础。我们在后…

康佳Android面试题及参考答案(多张原理图)

JVM 内存分布和分代回收机制是什么? JVM 内存主要分为以下几个区域。 堆(Heap)是 JVM 管理的最大的一块内存区域,主要用于存放对象实例。所有线程共享堆内存,在堆中又分为年轻代(Young Generation)和老年代(Old Generation)。年轻代又分为 Eden 区和两个 Survivor 区(…

(css)element中el-select下拉框整体样式修改

(css)element中el-select下拉框整体样式修改 重点代码&#xff08;颜色可行修改&#xff09; // 修改input默认值颜色 兼容其它主流浏览器 /deep/ input::-webkit-input-placeholder {color: rgba(255, 255, 255, 0.50); } /deep/ input::-moz-input-placeholder {color: rgba…