Redis 作为消息队列的三种使用方式与 Spring Boot 实践

目录

  1. Redis 为什么能够作为消息队列
  2. 三种消息队列实现方式概览
  3. Redis List 队列机制及 Spring 实战
  4. Redis Pub/Sub 发布订阅机制及使用方式
  5. Redis Stream:最强队列机制(含 ACK、消费组)
  6. Spring Boot 整合 Stream(完整可运行)
  7. Redis Stream 与 Kafka 的特点对比
  8. 使用场景总结

1. Redis 为什么可以用作消息队列

Redis 是一个基于内存的高性能 Key-Value 数据库,它的数据结构丰富且操作均为 O(1)。

队列的本质是"先进先出,按顺序取出",而 Redis 的 List、Pub/Sub 与 Stream 结构分别可以满足不同层次的队列需求:

  • List:可以充当普通队列
  • Pub/Sub:提供实时的发布订阅
  • Stream:提供带持久化、消费组、ACK 确认机制的专业队列能力

这让 Redis 在轻量级 MQ 场景下非常灵活,也非常高效。


2. Redis 三种消息队列方案对比

方案 持久化 是否丢消息 是否支持消费组 是否需要 ACK 使用难度 适用场景
List(LPUSH/RPOP) 支持 有可能丢失 不支持 不支持 最简单 简单后台任务、异步执行
Pub/Sub 不支持 订阅者离线即丢失 不支持 不支持 中等 实时消息推送、广播通知
Stream 支持 不容易丢失 支持 支持 相对复杂 订单处理、任务调度、分布式队列

从功能完善度来看,Stream 是最推荐的方案。

从使用简单度来看,List 是最容易上手的。


3. Redis List 队列机制(LPUSH + RPOP)

List 是 Redis 最经典的队列实现方式。通过"左进右出"就可以模拟一个典型的 FIFO 队列。

特点说明

  1. 实现简单,可快速上手
  2. 使用 RedisTemplate 就能轻松实现
  3. 不支持消费者确认机制,消息投递后无法保证成功处理
  4. 多消费者会导致竞争同一条消息,不适合任务分布式分发

因此,List 更适合简易异步任务、低可靠场景。

生产者示例:

java 复制代码
@Autowired
private StringRedisTemplate redisTemplate;

public void sendMessage(String msg) {
    redisTemplate.opsForList().leftPush("task_queue", msg);
}

消费者示例:

java 复制代码
@Scheduled(fixedDelay = 1000)
public void consumer() {
    String msg = redisTemplate.opsForList().rightPop("task_queue");
    if (msg != null) {
        System.out.println("处理任务:" + msg);
    }
}

这种方式虽然简单,但不具备强队列能力。


4. Redis Pub/Sub 发布订阅模式

Pub/Sub 提供了一种非常实时化的消息推送方式,它不存储历史消息,只有在线订阅者才能收到。

模式特点

  1. 适合实时通知,如系统消息、广播消息、在线聊天
  2. 不会保存消息,订阅者掉线即丢失
  3. 没有 ACK,无法保证每条消息被处理

Pub/Sub 不适合作为任务队列,但适合"实时推送"。

监听器配置

java 复制代码
@Configuration
public class RedisConfig {

    @Bean
    MessageListenerAdapter listenerAdapter(MessageReceiver receiver) {
        return new MessageListenerAdapter(receiver, "onMessage");
    }

    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory factory,
                                            MessageListenerAdapter listenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);
        container.addMessageListener(listenerAdapter, new PatternTopic("notice"));
        return container;
    }
}

消费者

java 复制代码
@Component
public class MessageReceiver {
    public void onMessage(String message) {
        System.out.println("收到通知:" + message);
    }
}

生产者

java 复制代码
redisTemplate.convertAndSend("notice", "系统通知:服务器即将维护");

5. Redis Stream:专业级消息队列方案

Stream 是 Redis 5.0 引入的全新数据结构,是一套完整的消息队列系统,特点如下:

  1. 支持持久化,数据不会因断电丢失
  2. 支持消费者组,可由多个消费者组成消费集群
  3. 支持 ACK 确认机制,确保消息不会丢失
  4. 单条消息被确定处理后自动从 Pending 列表中移除
  5. 支持自动或手动 Claim,保证消息不会被遗忘
  6. 顺序性和性能都非常优秀

Stream 可以被认为是小型版的 Kafka,但更轻量、更容易部署。


6. Spring Boot 整合 Redis Stream

1)依赖引入

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2)初始化消息队列的消费组

为了防止不存在的消费组导致报错,一般在项目启动时创建消费组:

java 复制代码
@Component
public class StreamInit {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @PostConstruct
    public void init() {
        try {
            redisTemplate.opsForStream().createGroup("order_stream", "order_group");
        } catch (Exception ignored) {}
    }
}

3)生产者发送消息

java 复制代码
@Autowired
private StringRedisTemplate redisTemplate;

public void sendOrder(String orderNo) {
    Map<String, String> map = new HashMap<>();
    map.put("orderNo", orderNo);
    redisTemplate.opsForStream().add("order_stream", map);
}

4)消费者处理消息(包含 ACK)

java 复制代码
@Component
public class OrderConsumer implements StreamListener<String, MapRecord<String, String, String>> {

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public void onMessage(MapRecord<String, String, String> record) {
        String orderNo = record.getValue().get("orderNo");
        System.out.println("正在处理订单:" + orderNo);

        redisTemplate.opsForStream().acknowledge("order_stream", "order_group", record.getId());
    }
}

5)注册 Stream 监听器

java 复制代码
@Configuration
public class StreamConfig {

    @Bean
    public RedisMessageListenerContainer listenerContainer(
            RedisConnectionFactory factory,
            OrderConsumer consumer) {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(factory);

        StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, MapRecord<String, String, String>> options =
                StreamMessageListenerContainer.StreamMessageListenerContainerOptions
                        .builder()
                        .pollTimeout(Duration.ofSeconds(2))
                        .build();

        StreamMessageListenerContainer<String, MapRecord<String, String, String>> streamContainer =
                StreamMessageListenerContainer.create(factory, options);

        streamContainer.receiveAutoAck(
                Consumer.from("order_group", "consumer_1"),
                StreamOffset.create("order_stream", ReadOffset.lastConsumed()),
                consumer
        );

        streamContainer.start();
        return container;
    }
}

至此,Redis Stream 的生产-消费整体链路完整实现,可以直接在实际项目中使用。


7. Redis Stream 与 Kafka 的对比分析

特点 Redis Stream Kafka
吞吐量 中等偏高 极高
消费机制 消费组 + ACK 消费组 + Offset
持久化方式 内存主导 + AOF 磁盘顺序写
依赖环境 极简,部署容易 较复杂,需要 Zookeeper 或 Kraft
使用场景 中小型业务,订单流、异步任务 海量日志、实时流处理、大型数据系统

结论: 当系统规模较小时,Redis Stream 是简单高效的队列方案;当系统达到大规模吞吐需求时,Kafka 才是更合适的选择。


8. 使用场景总结

以下场景适合完全使用 Redis Stream 或 List/PubSub:

  • 订单创建后的异步处理
  • 秒杀请求异步落库
  • 延迟任务队列
  • 短信/邮件异步发送
  • 系统通知、用户消息推送
  • 日志或审计消息收集
  • 数据同步、事件驱动架构

Redis 的灵活性使它能够同时承担缓存、分布式锁和消息队列等多种角色,适用于多种中小型分布式系统架构。


结语

Redis 不仅是一个高性能的缓存数据库,同时也是一个非常灵活且强大的轻量级消息队列解决方案。依托于其多样化的数据结构、极高的读写性能以及简单易部署的特点,Redis 在现代微服务架构中扮演着远超"缓存"本身的角色。在许多中小型项目中,它可以承担消息传递、事件驱动、异步任务处理等职责,甚至可以在一定程度上替代专业消息中间件。

在 Spring 体系中,Redis 的集成方式非常成熟且丰富,无论是基于 List 的简易队列、基于 Pub/Sub 的实时广播消息,还是基于 Stream 的分布式消息队列,都可以通过 Spring Data Redis 顺畅地接入应用系统。其中 Redis Stream 是目前最值得推荐的方案,它具备消息持久化、消费者组、消息确认机制(ACK)、Pending 列表管理、顺序性保证等能力,能够提供接近 Kafka 那样的消息投递可靠性,同时又保持了 Redis 一贯的简单部署和轻量成本。

相关推荐
GreatSQL社区2 小时前
GreatSQL MGR三节点基于时间点恢复
数据库·oracle
小坏讲微服务2 小时前
Spring Boot 4.0 + MyBatis-Plus 实战响应式编程的能力实战
java·spring boot·后端·mybatis
张较瘦_2 小时前
Springboot3 | JUnit 5 使用详解
spring boot·junit
李慕婉学姐2 小时前
Springboot遇见宠物生活馆系统设计与实现n6ea5118(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·宠物
BAStriver2 小时前
关于Flowable的使用小结
java·spring boot·spring·flowable
2501_941982052 小时前
企业微信客户联系API中 添加客户 与 发送欢迎语 的异步处理优化
服务器·数据库·php
想不明白的过度思考者2 小时前
MySQL 数据类型详解
数据库·mysql
Dolphin_Home2 小时前
Java Stream 实战:订单商品ID过滤技巧(由浅入深)
java·开发语言·spring boot
晓13132 小时前
SQL篇——【MySQL篇:SQL理论】SQL 与关系型数据库核心要点详解
数据库·mysql