三大开源消息队列(Kafka、RabbitMQ、RocketMQ)使用教程

首先我们来接一下什么是消息队列:消息队列(Message Queue,简称 MQ)是一种跨进程、异步通信的中间件技术 ,用于在分布式系统中解耦生产者与消费者、削峰填谷、保证最终一致性

使用的场景是:

应用解耦

  • 场景:订单服务创建订单后,需通知库存、物流、积分系统。

  • 不用 MQ:订单服务直接调用 3 个接口 → 任一系统宕机,订单失败。

  • 用 MQ:各系统独立消费,互不影响。

异步处理

  • 场景:用户上传头像 → 生成缩略图、更新 CDN、记录审计日志。

  • 同步做法:用户等待 3 秒才看到"上传成功"。

  • 异步做法 :j

    → 用户体验提升,系统响应更快。


流量削峰(应对高并发)

  • 场景:双 11 秒杀,10 万 QPS 瞬间打到数据库。

  • 不用 MQ:数据库连接池耗尽,服务雪崩。

  • 用 MQ

    • 前端请求只写入 MQ(写速度极快);

    • 后端以 1000 QPS 的稳定速度消费;

    • 系统不崩溃,只是延迟几秒处理

💡 类似"排队买票":窗口处理不过来,先让人在大厅排队(MQ),避免踩踏(系统崩溃)。


最终一致性(分布式事务)

  • 场景 :支付成功后,必须 同时 扣减账户余额 + 增加商品销量。

  • 问题:两个操作跨数据库,无法用本地事务。

  • MQ 方案(可靠事件模式)

    1. 支付服务:BEGIN; 扣余额; 发送"支付成功"消息; COMMIT;

    2. 商品服务:消费消息 → 增加销量

    3. 若消息丢失?→ 用 事务消息 (RocketMQ)或 本地消息表 补偿

✅ 保证:要么都成功,要么通过重试最终成功。


日志收集 & 大数据 pipeline

  • 场景:收集 App 用户点击行为,用于实时分析。

  • 架构 :文本

    复制代码
    App → Kafka → Flink 实时计算 → 大屏展示
                  ↘ Spark 离线分析 → 用户画像
  • 优势:Kafka 高吞吐(百万级/秒),持久化存储,支持重放。

1.三大开源消息队列的特征和差异

特性 Apache Kafka RabbitMQ Apache RocketMQ
设计目标 高吞吐、日志流、事件溯源 可靠传递、复杂路由 高可靠、金融级事务、低延迟
吞吐量 ⭐⭐⭐⭐⭐(10万~百万+/秒) ⭐⭐(万级/秒) ⭐⭐⭐⭐(10万+/秒)
延迟 中(毫秒级) 低(微秒~毫秒) 低(毫秒级)
消息可靠性 高(可配置) 极高(持久化+ACK) 极高(同步刷盘+主从)
消息模型 发布/订阅(基于 Topic + 分区) AMQP(Exchange + Queue) 发布/订阅 + 点对点
事务支持 ✅(Exactly-Once,需开启) ❌(仅 confirm 模式) ✅(分布式事务,2PC)
顺序消息 ✅(分区级有序) ❌(不保证全局有序) ✅(严格全局有序)
运维复杂度 中高(需理解分区/副本) 低(开箱即用) 中(NameServer + Broker)
典型用户 LinkedIn、Netflix、阿里日志 微服务解耦、任务队列 阿里电商、金融交易

1.1Apache Kafka ------ "大数据管道之王"

✅ 核心优势:

  • 超高吞吐:顺序写磁盘 + 批处理 + 零拷贝,轻松支撑百万级 TPS;

  • 持久化存储:消息可保留数天至数月,支持重放;

  • 水平扩展:增加 Broker 节点即可扩容;

  • 生态系统强大:Kafka Streams、ksqlDB、Connect 等。

⚠️ 局限:

  • 延迟较高(不适合实时交互);

  • 不支持复杂路由(如通配符、优先级队列);

  • 运维需理解 ISR、Controller、分区再平衡等概念。

🎯 适用场景

  • 日志收集(ELK 替代方案)

  • 用户行为分析(埋点数据流)

  • 事件溯源 / CQRS

  • 大数据 pipeline(Flink / Spark Streaming 数据源)

  • 异步解耦(高吞吐场景)

💡 典型例子

订单消息 → Kafka → 实时计算引擎 → 大屏监控


1.2 RabbitMQ ------ "企业级可靠消息中间件"

✅ 核心优势:

  • 协议标准:基于 AMQP 0.9.1,多语言支持好;

  • 灵活路由:支持 Direct、Topic、Fanout、Headers 四种 Exchange;

  • 消息确认机制:Publisher Confirm + Consumer ACK,确保不丢;

  • 管理界面友好:Web UI 监控队列、连接、速率;

  • 插件生态:延迟队列、MQTT、STOMP 等。

⚠️ 局限:

  • 吞吐量较低(单队列约 1~2 万/秒);

  • 集群模式(Mirrored Queue)扩展性差;

  • 内存占用高(消息先入内存)。

🎯 适用场景

  • 微服务间可靠通信(订单 → 库存 → 物流)
  • 任务队列(邮件发送、图片处理)
  • 需要复杂路由的场景 (如:order.*.paid 匹配多个服务)
  • 对消息可靠性要求极高,但吞吐不高

💡 典型例子

用户注册 → 发送欢迎邮件(RabbitMQ 延迟队列 5 分钟后触发)


1.3Apache RocketMQ ------ "金融级消息引擎"

✅ 核心优势:

  • 高可靠 + 低延迟:同步双写 + 主从架构,金融级 SLA;

  • 严格顺序消息:同一订单 ID 的消息全局有序;

  • 事务消息:两阶段提交,解决"本地事务 + 发消息"一致性;

  • 消息轨迹:可追踪消息全生命周期;

  • 削峰填谷:支持海量堆积(TB 级)。

⚠️ 局限:

  • 社区活跃度略低于 Kafka;

  • 生态工具较少(无原生流处理);

  • 配置稍复杂(NameServer + Broker + Producer/Consumer)。

🎯 适用场景

  • 电商交易系统(下单、支付、履约)

  • 金融核心链路(转账、清算)

  • 需要分布式事务的场景

  • 强顺序要求(如:股票交易指令)

用户支付成功 → RocketMQ 事务消息 → 更新订单状态 + 扣减库存(原子性)

2.使用

2.1RabbitMQ使用

1.安装

我们可以在自己的云服务器安装RabbitMQ服务(网上教程很多,此步省略),还可以通过云服务直接购买,生产环境我们推荐云服务商的产品,稳定可靠

2.导入依赖(我们以java语言为例子)

XML 复制代码
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

3.编码

yml配置文件如下:

java 复制代码
spring  
  rabbitmq:
    host: 换成你的
    port: 5672
    username: xxx
    password: xxx

简单解释一下下面这代代码的意思:创建私信交换器,创建两个队列,生成死信,发送延迟消息的方法,发送端调用sendDelayedMessage方法即可

java 复制代码
/**
 * @Author xjy
 * @Date 2025/4/17 14:37
 */
@Configuration
public class RabbitMQConfig {

   @Resource
   private RabbitTemplate template;
   //1.创建 死信交换器  专门转发死信消息
   @Bean("dead")
   public DirectExchange createDLX(){
      return new DirectExchange("deadex");
   }
   //2.创建队列
   //队列 生成死信 1.没有消费者 2.有效期 3.设置死信和死信匹配关键字
   @Bean
   public Queue createQ1() {
      Map<String, Object> param = new HashMap<>();
      //设置死信交换器
      param.put("x-dead-letter-exchange", "deadex");
      //设置死信交换器 匹配的路由
      param.put("x-dead-letter-routing-key", "demo");
      return QueueBuilder.durable("quene01").withArguments(param).build();
   }

   @Bean
   public Queue createQ2(){
      return new Queue("quene02");
   }
   //3.绑定
   @Bean
   public Binding createBd8(@Qualifier("dead") DirectExchange dead){
      //any 任意1个即可
      return BindingBuilder.bind(createQ2()).to(dead).with("demo");
   }
   /**
    * 发送带有动态 TTL 的消息
    *
    * @param messageContent 消息内容
    * @param ttlMillis      消息的 TTL(单位:毫秒)
    */
   public void sendDelayedMessage(String messageContent, long ttlMillis) {
      // 创建消息属性对象
      MessageProperties messageProperties = new MessageProperties();
      // 设置消息的 TTL
      messageProperties.setExpiration(String.valueOf(ttlMillis));
      // 设置消息的内容类型为 text/plain
      messageProperties.setContentType("text/plain");
      // 设置字符集为 UTF-8
      messageProperties.setContentEncoding("UTF-8");

      // 创建消息对象
      Message message = new Message(messageContent.getBytes(StandardCharsets.UTF_8), messageProperties);

      // 发送消息
      template.send("quene01", message);
   }
}

消费端处理延迟消息如下:

java 复制代码
@Component
@RabbitListener(queues = "quene02")
public class DqListener {
   
    @RabbitHandler
    public void handler(String msg){
        //延迟接收消息,处理业务即可
        }
    }
}

到此,我们基于死信消息实现的延迟队列就实现了,基于这个逻辑同样可以实现订单超时取消,用户注册 → 发送欢迎邮件(RabbitMQ 延迟队列 5 分钟后触发)等功能

测试功能如下:

2.2RocketMQ使用

安装省略,同样的,你可以在服务器上自定义安装,或者使用钞能力购买云服务产品

导入依赖

java 复制代码
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-client-java</artifactId>
    <version>5.3.0</version>
</dependency>

生产者:

java 复制代码
import org.apache.rocketmq.client.apis.ClientException;
import org.apache.rocketmq.client.apis.producer.Producer;
import org.apache.rocketmq.client.apis.producer.SendReceipt;
import org.apache.rocketmq.client.java.ClientConfig;
import org.apache.rocketmq.client.java.producer.ProducerBuilder;

import java.util.Collections;

public class OrderProducer {

    // 替换为您的 NameServer 地址(多个用分号隔开)
    private static final String ENDPOINTS = "192.168.1.10:9876;192.168.1.11:9876";

    public static void main(String[] args) throws ClientException {
        // 1. 创建 Producer 配置
        ClientConfig config = ClientConfig.newBuilder()
                .setEndpoints(ENDPOINTS)
                .build();

        // 2. 构建 Producer
        Producer producer = ProducerBuilder.newBuilder(config)
                .setTopics(Collections.singletonList("ORDER_TOPIC")) // 预声明 Topic(可选)
                .build();

        // 3. 发送消息
        String messageBody = "{\"orderId\":\"1001\",\"action\":\"CREATE\"}";
        SendReceipt sendReceipt = producer.send(
                "ORDER_TOPIC",          // Topic
                "ORDER_GROUP",          // Tag(可选,用于过滤)
                messageBody.getBytes()  // 消息体(byte[])
        );

        System.out.println("Message sent! Message ID: " + sendReceipt.getMessageId());
        producer.close();
    }
}

消费者:

java 复制代码
import org.apache.rocketmq.client.apis.ClientException;
import org.apache.rocketmq.client.apis.consumer.ConsumeResult;
import org.apache.rocketmq.client.apis.consumer.FilterExpression;
import org.apache.rocketmq.client.apis.consumer.PushConsumer;
import org.apache.rocketmq.client.java.ClientConfig;
import org.apache.rocketmq.client.java.consumer.ConsumeResultStatus;
import org.apache.rocketmq.client.java.consumer.PushConsumerBuilder;

import java.nio.charset.StandardCharsets;
import java.util.Collections;

public class OrderConsumer {

    private static final String ENDPOINTS = "192.168.1.10:9876;192.168.1.11:9876";

    public static void main(String[] args) throws ClientException, InterruptedException {
        // 1. 创建 Consumer 配置
        ClientConfig config = ClientConfig.newBuilder()
                .setEndpoints(ENDPOINTS)
                .build();

        // 2. 构建 Consumer
        PushConsumer consumer = PushConsumerBuilder.newBuilder(config)
                .setSubscriptionExpressions(Collections.singletonMap(
                        "ORDER_TOPIC", 
                        FilterExpression.SUB_ALL  // 订阅所有消息(或指定 Tag)
                ))
                .setMessageListener(messageView -> {
                    try {
                        // 解析消息
                        String body = new String(messageView.getBody(), StandardCharsets.UTF_8);
                        String topic = messageView.getTopic();
                        String tag = messageView.getTag(); // 可能为 null

                        System.out.println("Received message: " + body);
                        // TODO: 处理业务逻辑(如更新订单状态)

                        return ConsumeResult.SUCCESS; // 成功
                    } catch (Exception e) {
                        e.printStackTrace();
                        return ConsumeResult.FAILURE; // 失败,会重试
                    }
                })
                .build();

        System.out.println("Consumer started...");
        // 保持进程运行
        Thread.sleep(Long.MAX_VALUE);
    }
}

2.1Kafka使用

安装省略,同样的,你可以在服务器上自定义安装,或者使用钞能力购买云服务产品

导入依赖

java 复制代码
<dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>

yml配置文件

java 复制代码
spring:
  kafka:
    bootstrap-servers:  # Kafka 集群地址,确保多个服务器,提高可靠性
    consumer:
      group-id: ""  # 消费者组 ID
      auto-offset-reset: latest  # 自动偏移量重置为最新,避免每次启动都从头消费
      enable-auto-commit: true  # 自动提交偏移量
      auto-commit-interval: 1000  # 自动提交偏移量的间隔时间(毫秒)
      max-poll-records: 500  # 每次批量拉取消息的最大数量
    producer:
      key-serializer: org.apache.kafka.common.serialization.StringSerializer  # 消息的键序列化器
      value-serializer: org.apache.kafka.common.serialization.StringSerializer # 消息的值序列化器

生产者:

java 复制代码
 @Resource
    private KafkaTemplate<String, String> kafkaTemplate;
    @Resource
    private ObjectMapper objectMapper;

    //每一分钟执行一次
    @Scheduled(cron = "0 0/1 * * * ?")
    public void handlerOrder() {

        //模拟发送消息 vopBizTransMessage为任意对象,可以改成自己的类对象即可,在消费端解析,key为统一标识,可以传订单id,商品id这些,可以分组有序
        kafkaTemplate.send("换成你的topic主题", "key", objectMapper.writeValueAsString(vopBizTransMessage));

    }

消费者:

java 复制代码
@Slf4j
@Component
public class JdVopOrderConsumer {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @KafkaListener(
            topics = "jd_vop_order",
            groupId = "jd_vop_message_dev"  // 必须与配置中的 group-id 一致
    )
    public void listen(String message) {
        try {
            log.info("Received raw message: {}", message);

            // 反序列化为业务对象
            VopBizTransMessage vopMessage = objectMapper.readValue(message, VopBizTransMessage.class);

            // TODO: 处理业务逻辑(如更新订单状态、触发后续流程等)
            processOrder(vopMessage);

        } catch (Exception e) {
            log.error("Failed to process Kafka message: {}", message, e);
            // TODO: 考虑死信队列或重试机制(见下文)
        }
    }

    private void processOrder(VopBizTransMessage message) {
        // 示例:打印订单号
        log.info("Processing order: {}", message.getContent());
        // 实际业务:调用订单服务、库存服务等
    }
}

到此,我们就实现了消息队列的生产和消费,下面我们开始测试流程:

3.总结

相关推荐
lucky_syq2 小时前
Mac电脑部署OpenClaw保姆级教程(2026最新版)
人工智能·macos·开源·电脑·openclaw
PNP Robotics2 小时前
PNP机器人亮相第二届机器人灵巧手国际创新大会
人工智能·学习·机器人·开源
草梅友仁2 小时前
墨梅博客 1.10.0 发布与 AI 编程工作流优化 | 2026 年第 12 周草梅周报
开源·github·ai编程
GoCodingInMyWay11 小时前
开源好物 26/03
人工智能·开源
百锦再12 小时前
Java 并发编程进阶,从线程池、锁、AQS 到并发容器与性能调优全解析
java·开发语言·jvm·spring·kafka·tomcat·maven
Hommy8814 小时前
【开源剪映小助手】IPC 通信机制
python·开源·aigc·剪映小助手
我真会写代码16 小时前
从入门到精通:Kafka核心原理与实战避坑指南
分布式·缓存·kafka
程序员Better17 小时前
一口气拆穿Skill/MCP/RAG/Agent/OpenClaw底层逻辑
人工智能·开源·agent
一叶飘零_sweeeet17 小时前
击穿 Kafka 高可用核心:分区副本、ISR 机制与底层原理全链路拆解
分布式·架构·kafka