SpringBoot 整合 Redis 实现消息发布订阅实战

举报
JiHua 发表于 2026/10/23 12:14:53 2026/10/23
【摘要】 在后端开发中,很多场景需要实现模块解耦、异步通知,比如订单状态变更通知、系统配置刷新、日志告警推送等。Redis 自带的 Pub/Sub 发布订阅模式轻量易用,不需要额外部署消息中间件,非常适合简单的消息通知场景。本文基于 SpringBoot 整合 RedisTemplate,手把手实现消息发布、消息监听订阅,附带完整可运行代码

前言

消息队列是后端解耦的常用方案,但很多小型项目、内部管理系统,只是需要简单的事件通知,如果单独部署 RabbitMQ 会增加运维成本。Redis 原生支持 Pub/Sub 发布订阅模型,它是一种广播模式:发布者向指定频道发送消息,所有订阅该频道的消费者都能收到消息。

⚠️ 注意:Redis Pub/Sub 不是持久化消息队列。消息发送时,如果消费者离线,这条消息直接丢失,不会缓存。所以它适合通知类场景,不适合订单支付、库存扣减这类不能丢消息的业务。

一、环境依赖

SpringBoot 版本 2.7.x,引入 spring-boot-starter-data-redis:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

application.yml 配置 Redis 连接:

spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password:
    database: 0

二、配置消息监听容器

想要订阅 Redis 频道消息,需要配置 MessageListenerContainer,绑定消息监听处理器。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

@Configuration
public class RedisPubSubConfig {

    // 定义监听的频道
    public static final String TOPIC_SYSTEM_NOTIFY = "system:notify";

    // 消息监听适配器,绑定处理类
    @Bean
    public MessageListenerAdapter listenerAdapter(RedisMessageReceiver receiver) {
        // 指定接收消息后执行的方法名
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

    // 监听容器
    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory factory,
                                                   MessageListenerAdapter listenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        // 订阅指定频道
        container.addMessageListener(listenerAdapter, new ChannelTopic(TOPIC_SYSTEM_NOTIFY));
        return container;
    }
}

三、消息接收处理器

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class RedisMessageReceiver {

    /**
     * 消息接收方法
     * @param message 收到的消息字符串
     */
    public void receiveMessage(String message) {
        log.info("【Redis订阅收到消息】:{}", message);
        // 这里写业务逻辑:刷新配置、推送站内通知、打印告警等
    }
}

四、消息发布工具类/测试接口

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
@RequestMapping("/redis/pub")
public class RedisPubController {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @GetMapping("/send")
    public String sendMsg(@RequestParam String content) {
        redisTemplate.convertAndSend(RedisPubSubConfig.TOPIC_SYSTEM_NOTIFY, content);
        return "消息发布成功:" + content;
    }
}

五、测试流程

  1. 启动 SpringBoot 项目,容器会自动订阅 system:notify 频道
  2. 浏览器访问接口:[http://127.0.0.1:8080/redis/pub/send?content=](http://127.0.0.1:8080/redis/pub/send?content=)系统配置已更新
  3. 查看控制台日志,可以看到 【Redis订阅收到消息】:系统配置已更新

六、核心特性与坑点总结

  1. 广播机制:同一个频道多个订阅者,消息会发给所有订阅者;不是点对点消费,没有 ack 确认。
  2. 消息不持久化:消费者离线期间发布的消息直接丢失,重启后收不到历史消息。
  3. 不支持消息堆积:Redis Pub/Sub 没有队列,消息发送瞬间分发完毕,无法回溯。
  4. 序列化问题:如果 RedisTemplate 使用 JdkSerializationRedisSerializer,消息会带序列化前缀,监听端拿到的是二进制。推荐使用 StringRedisTemplate 处理纯文本消息。
  5. 频道和模式订阅:除了固定 ChannelTopic,还支持 PatternTopic 通配符订阅,例如 system:* 匹配所有 system 开头频道。

七、选型对比

方案 优点 缺点 适用场景
Redis Pub/Sub 零额外部署、代码简单、低延迟 消息丢失、无堆积、无重试 配置刷新、实时通知、日志广播
RabbitMQ 消息持久化、ACK、重试、死信队列 需要独立部署、运维复杂 订单、支付、库存等可靠业务

八、生产环境优化建议

  1. 消息体尽量简短复杂对象建议序列化为 JSON 字符串传输;
  2. 消息消费逻辑做好 try-catch,避免单个消息异常导致监听线程卡死;
  3. 重要业务不要依赖 Redis Pub/Sub,优先专业 MQ;
  4. 监听容器可以配置线程池,提高消息并发消费能力。

结语

Redis Pub/Sub 是一个轻量化的事件通知方案,门槛很低,适合快速实现系统内异步解耦。很多新手容易把它当成可靠消息队列使用,最后出现消息丢失问题。理解它的底层限制,在合适场景下使用,才能发挥它的价值。本篇代码可以直接复制到项目中运行,快速验证发布订阅能力。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。