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

目录

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

bash 复制代码
sudo apt-get install libhiredis-dev
1.2.2 发布者(Publisher)

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

cpp 复制代码
#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++ 实现代码:

cpp 复制代码
#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++ 示例代码:

cpp 复制代码
#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++ 示例代码:

cpp 复制代码
#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

相关推荐
朦胧之1 天前
AI 编程-老项目改造篇
java·前端·后端
程序猿大帅1 天前
别再只当调包侠了:用 Spring AI 落地 Function Calling,我被大模型硬生生砸出了三个大坑
java
AlfredZhao1 天前
Docker 容器时区不对,`timedatectl` 不存在怎么办?
linux·timezone
程序员晓琪1 天前
约定大于配置:基于 Java 包名自动生成 API 版本路由的最佳实践
java·spring boot·后端
Flittly1 天前
【AgentScope Java新手村系列】(11)中断与恢复
java·spring boot·spring
众少成多积小致巨1 天前
JNI (Java Native Interface) 技术手册中文参考指南
android·java·c++
东坡白菜1 天前
破局全栈:前端开发的Java入门实战记录—JPA(2)
java·后端
SimonKing1 天前
艹,维护AI写的代码,我心态崩了......
java·后端·程序员
用户298698530141 天前
Java Word 文档样式进阶:段落与文本背景色设置完全指南
java·后端
小bo波2 天前
从"任意文件复制"深挖Java I/O:字符流与字节流的本质抉择
java·nio·io流·后端开发·文件复制