rocketmq学习

1. RocketMQ 是什么?

RocketMQ 是一个消息队列中间件

它的核心作用是:

让一个系统把消息发出去,另一个系统异步接收并处理。

比如:

text 复制代码
订单系统  --->  RocketMQ  --->  库存系统
订单系统  --->  RocketMQ  --->  积分系统
订单系统  --->  RocketMQ  --->  短信系统

订单系统只负责说:

"用户下单了。"

然后把这条消息发到 RocketMQ。

库存系统看到这个消息,就扣库存。

积分系统看到这个消息,就加积分。

短信系统看到这个消息,就发短信。

这样订单系统就不需要自己一个个调用它们。


2. 为什么要用 RocketMQ?

主要解决这几个问题。

1)异步处理,提高速度

不用消息队列时:

text 复制代码
下单 -> 扣库存 -> 加积分 -> 发短信 -> 返回成功

用户要等所有步骤完成。

用了 RocketMQ:

text 复制代码
下单 -> 发送消息 -> 返回成功

扣库存、加积分、发短信后面慢慢处理。

这样接口响应更快。


2)系统解耦

不用 MQ 时,订单系统可能要直接调用库存系统、短信系统、积分系统。

text 复制代码
订单系统强依赖库存系统
订单系统强依赖短信系统
订单系统强依赖积分系统

如果短信系统挂了,订单系统可能也受影响。

用了 MQ:

text 复制代码
订单系统只管发消息
其他系统自己订阅消息

订单系统不用关心谁来处理。


3)削峰填谷

比如秒杀场景,一瞬间来了 10 万个请求。

如果这些请求直接打到数据库,数据库可能崩。

可以先把请求写入 MQ:

text 复制代码
大量请求 -> RocketMQ -> 后台慢慢消费 -> 数据库

RocketMQ 相当于一个缓冲池。


3. RocketMQ 里的核心概念

你先记住这些:

text 复制代码
Producer:生产者,发消息的人
Consumer:消费者,收消息的人
Topic:消息主题,消息分类
Group:组,表示一类生产者或消费者
Broker:消息服务器,真正存消息的地方
NameServer:注册中心,帮客户端找到 Broker
Message:消息本身
Tag:Topic 下面的二级分类
Queue:Topic 内部的队列分片

下面一个个讲。


4. Topic 是什么?

Topic 是消息的分类。

比如你有这些业务:

text 复制代码
订单消息
支付消息
优惠券消息
库存消息

你可以设计成:

text 复制代码
order_topic
pay_topic
coupon_topic
stock_topic

Topic 就像一个"频道"。

生产者发送消息时,要指定发到哪个 Topic。

消费者订阅消息时,也要指定监听哪个 Topic。

例如:

text 复制代码
订单系统发送消息到 order_topic
库存系统监听 order_topic
积分系统监听 order_topic
短信系统监听 order_topic

只要有系统对订单消息感兴趣,就订阅 order_topic


Topic 的简单理解

你可以这样记:

text 复制代码
Topic = 消息属于哪一类

比如:

text 复制代码
下单成功消息 -> order_topic
支付成功消息 -> pay_topic
优惠券过期消息 -> coupon_topic

5. Group 是什么?

Group 分两种:

text 复制代码
Producer Group
Consumer Group

但实际开发里,你最需要理解的是 Consumer Group


5.1 Producer Group 是什么?

Producer Group 是生产者组。

它表示一类发送消息的生产者。

比如订单服务有多个实例:

text 复制代码
order-service-1
order-service-2
order-service-3

它们都负责发送订单消息,可以属于同一个 Producer Group:

text 复制代码
order_producer_group

小白阶段不用太纠结 Producer Group,它更多是标识生产者身份。


5.2 Consumer Group 是什么?

Consumer Group 是消费者组。

它非常重要。

它表示:

一组消费者共同消费同一类消息。

比如库存服务部署了 3 台机器:

text 复制代码
stock-service-1
stock-service-2
stock-service-3

它们都属于:

text 复制代码
stock_consumer_group

那么一条消息只会被这个组里的其中一个实例消费。

也就是说:

text 复制代码
order_topic 有一条消息:用户A下单了

stock-service-1 消费
stock-service-2 不消费
stock-service-3 不消费

这样可以分摊压力。


6. 一个 Topic 可以被多个 Group 消费吗?

可以,而且这是 RocketMQ 很重要的地方。

假设订单系统发了一条消息:

text 复制代码
Topic: order_topic
消息内容: 用户A下单成功

现在有三个系统都想处理这条消息:

text 复制代码
库存系统:扣库存
积分系统:加积分
短信系统:发短信

它们应该用不同的 Consumer Group:

text 复制代码
stock_consumer_group
point_consumer_group
sms_consumer_group

这样这条消息会被每个 Group 都消费一次。

也就是:

text 复制代码
stock_consumer_group 消费一次
point_consumer_group 消费一次
sms_consumer_group 消费一次

但是在同一个 Group 内部,只会有一个消费者实例消费这条消息。


7. Topic 和 Group 的关系

这是最容易混乱的地方。

你可以这样理解:

text 复制代码
Topic:消息分类
Group:谁来消费这一类消息

举个例子:

text 复制代码
Topic: order_topic

Consumer Group:
- stock_group:库存系统消费
- sms_group:短信系统消费
- point_group:积分系统消费

关系图:

text 复制代码
订单系统
  |
  | 发送订单消息
  v
order_topic
  |
  |---- stock_group  -> 扣库存
  |
  |---- sms_group    -> 发短信
  |
  |---- point_group  -> 加积分

所以:

text 复制代码
同一个 Topic 可以被多个 Group 订阅。
不同 Group 都能拿到同一份消息。
同一个 Group 内部多个消费者是竞争消费。

8. Consumer Group 最重要的规则

假设:

text 复制代码
Topic = order_topic
Consumer Group = stock_group

如果你启动了 3 个库存服务实例:

text 复制代码
stock-service-1
stock-service-2
stock-service-3

它们都用同一个 stock_group

那么消息会被负载均衡:

text 复制代码
消息1 -> stock-service-1
消息2 -> stock-service-2
消息3 -> stock-service-3
消息4 -> stock-service-1

这叫集群消费

默认常用的就是这种。


如果你想让每个实例都收到同一条消息,那叫广播消费

比如:

text 复制代码
消息1 -> stock-service-1
消息1 -> stock-service-2
消息1 -> stock-service-3

但业务开发中更常用的是集群消费。


9. Tag 是什么?

Tag 是 Topic 下面更细的分类。

比如你有一个 Topic:

text 复制代码
order_topic

但是订单消息里面又分:

text 复制代码
下单成功
订单取消
订单超时
订单完成

可以用 Tag:

text 复制代码
order_topic: create
order_topic: cancel
order_topic: timeout
order_topic: finish

消费者可以只订阅自己关心的 Tag。

比如库存系统只关心:

text 复制代码
order_topic 下的 create 和 cancel

短信系统只关心:

text 复制代码
order_topic 下的 create

简单记:

text 复制代码
Topic = 大分类
Tag = 小分类

10. Message 是什么?

Message 就是消息本身。

一般包括:

text 复制代码
Topic
Tag
Key
Body

例如:

json 复制代码
{
  "topic": "order_topic",
  "tag": "create",
  "key": "order_10001",
  "body": {
    "orderId": 10001,
    "userId": 20001,
    "amount": 99.9
  }
}

其中:

text 复制代码
Topic:发到哪个主题
Tag:消息小分类
Key:消息唯一标识,方便排查
Body:真正的业务数据

11. Broker 是什么?

Broker 是 RocketMQ 里真正存消息的服务器。

生产者发送消息,实际上是发给 Broker。

消费者消费消息,也是从 Broker 拉消息。

text 复制代码
Producer -> Broker -> Consumer

如果说 RocketMQ 是快递系统,那么 Broker 就是快递仓库。


12. NameServer 是什么?

NameServer 类似注册中心。

它的作用是:

告诉 Producer 和 Consumer,Broker 在哪里。

因为生产者和消费者并不知道 Broker 地址,所以它们先连接 NameServer。

text 复制代码
Producer -> NameServer:请问 order_topic 在哪个 Broker?
NameServer -> Producer:在 Broker-A
Producer -> Broker-A:发送消息

你可以把 NameServer 理解成"地址簿"。


13. Queue 是什么?

一个 Topic 内部会分成多个 Queue。

比如:

text 复制代码
order_topic
  - queue0
  - queue1
  - queue2
  - queue3

为什么要分多个 Queue?

为了提高并发能力。

如果只有一个队列,一个消费者慢慢消费,速度有限。

多个 Queue 可以让多个消费者并行消费。

text 复制代码
queue0 -> consumer1
queue1 -> consumer2
queue2 -> consumer3
queue3 -> consumer4

小白阶段你不用主动操作 Queue,知道 Topic 内部有多个队列就行。


14. RocketMQ 的整体结构

完整流程大概是:

text 复制代码
NameServer:负责发现 Broker

Broker:负责存消息

Producer:发送消息

Consumer:消费消息

Topic:消息分类

Group:生产者/消费者分组

整体图:

text 复制代码
                NameServer
                    ^
                    |
        查询 Broker 地址
                    |
Producer  ----->  Broker  ----->  Consumer
   |                |               |
发送消息          存消息          拉取消息
   |
 Topic + Tag + Body

15. 开发中怎么设计 Topic 和 Group?

假设你做一个优惠券系统。

业务有:

text 复制代码
优惠券创建
优惠券领取
优惠券使用
优惠券过期

可以设计 Topic:

text 复制代码
coupon_topic

然后用不同 Tag:

text 复制代码
create
receive
use
expire

比如优惠券过期消息:

text 复制代码
Topic: coupon_topic
Tag: expire
Body: {"couponId": 1001}

消费者:

text 复制代码
coupon_expire_consumer_group

它监听:

text 复制代码
coupon_topic:expire

到时间后消费消息,把优惠券状态改成已过期。


16. RocketMQ 如何引入?以 Spring Boot 为例

常见方式是引入 RocketMQ Spring Boot Starter。

Maven 依赖一般类似这样:

xml 复制代码
<dependency>
    <groupId>org.apache.rocketmq</groupId>
    <artifactId>rocketmq-spring-boot-starter</artifactId>
    <version>2.3.0</version>
</dependency>

版本要根据你的 Spring Boot 和 RocketMQ 服务端版本调整。


17. 配置 application.yml

比如:

yaml 复制代码
rocketmq:
  name-server: 127.0.0.1:9876
  producer:
    group: order_producer_group

这里:

text 复制代码
name-server:NameServer 地址
producer.group:生产者组名

18. 生产者怎么发消息?

在 Spring Boot 里,可以用 RocketMQTemplate

java 复制代码
@RestController
@RequestMapping("/order")
public class OrderController {

    private final RocketMQTemplate rocketMQTemplate;

    public OrderController(RocketMQTemplate rocketMQTemplate) {
        this.rocketMQTemplate = rocketMQTemplate;
    }

    @PostMapping("/create")
    public String createOrder() {
        // 1. 模拟订单创建成功
        String orderId = "10001";

        // 2. 发送订单创建消息
        rocketMQTemplate.convertAndSend(
                "order_topic:create",
                "订单创建成功,订单ID:" + orderId
        );

        return "下单成功";
    }
}

这里:

java 复制代码
"order_topic:create"

表示:

text 复制代码
Topic = order_topic
Tag = create

19. 消费者怎么接收消息?

写一个监听器:

java 复制代码
@Component
@RocketMQMessageListener(
        topic = "order_topic",
        consumerGroup = "stock_consumer_group",
        selectorExpression = "create"
)
public class StockConsumer implements RocketMQListener<String> {

    @Override
    public void onMessage(String message) {
        System.out.println("库存系统收到订单消息:" + message);

        // 这里可以写扣库存逻辑
    }
}

解释一下:

java 复制代码
topic = "order_topic"

表示监听订单主题。

java 复制代码
consumerGroup = "stock_consumer_group"

表示这个消费者属于库存消费者组。

java 复制代码
selectorExpression = "create"

表示只消费 Tag 为 create 的消息。


20. 一个完整小例子

订单系统发消息

java 复制代码
rocketMQTemplate.convertAndSend(
        "order_topic:create",
        "用户下单成功,订单ID:10001"
);

库存系统消费消息

java 复制代码
@RocketMQMessageListener(
        topic = "order_topic",
        consumerGroup = "stock_consumer_group",
        selectorExpression = "create"
)
public class StockConsumer implements RocketMQListener<String> {

    @Override
    public void onMessage(String message) {
        System.out.println("扣库存:" + message);
    }
}

短信系统消费消息

java 复制代码
@RocketMQMessageListener(
        topic = "order_topic",
        consumerGroup = "sms_consumer_group",
        selectorExpression = "create"
)
public class SmsConsumer implements RocketMQListener<String> {

    @Override
    public void onMessage(String message) {
        System.out.println("发短信:" + message);
    }
}

注意,这两个消费者用了不同的 Consumer Group:

text 复制代码
stock_consumer_group
sms_consumer_group

所以同一条订单消息,库存系统和短信系统都能收到。


21. 如果两个消费者用了同一个 Group 会怎样?

比如:

java 复制代码
consumerGroup = "order_consumer_group"

两个消费者都用这个组。

那么同一条消息只会被其中一个消费者收到。

text 复制代码
消息1 -> 消费者A
消息2 -> 消费者B
消息3 -> 消费者A

这叫负载均衡。

所以千万记住:

text 复制代码
不同业务系统,要用不同 Consumer Group。
同一个业务系统的多个实例,用同一个 Consumer Group。

这是面试和实战都很重要的一句话。


22. RocketMQ 有哪些常见消息类型?

1)普通消息

最常用。

text 复制代码
订单创建后,发送一条订单消息

2)延迟消息

消息不是立刻消费,而是过一段时间再消费。

比如优惠券过期:

text 复制代码
优惠券 20 小时后过期

可以发送延迟消息:

text 复制代码
20 小时后消费者才收到消息

然后消费者把优惠券状态改为过期。

这就是你之前说的优惠券过期方案里可能会用到的方式。


3)顺序消息

保证消息按顺序消费。

比如订单状态变化:

text 复制代码
创建订单 -> 支付订单 -> 发货 -> 完成

这些消息最好按照顺序消费。


4)事务消息

解决"本地事务"和"发消息"一致性问题。

比如:

text 复制代码
订单创建成功后,必须发消息通知库存系统

如果订单创建成功了,但消息发送失败,就会出问题。

事务消息就是用来保证这类场景的一致性。


23. RocketMQ 使用中的几个重要问题

1)消息会不会重复消费?

会。

RocketMQ 不能保证业务层面绝对只消费一次。

所以消费者代码要做幂等

幂等是什么意思?

就是同一条消息消费多次,结果也一样。

比如扣库存时,不能简单写:

text 复制代码
库存 = 库存 - 1

否则重复消费就会多扣。

应该记录这条订单是否已经扣过库存:

text 复制代码
如果订单10001已经扣过库存,就不要重复扣

2)消息消费失败怎么办?

如果消费者抛异常,RocketMQ 会重试。

比如:

java 复制代码
@Override
public void onMessage(String message) {
    throw new RuntimeException("消费失败");
}

RocketMQ 会认为这条消息没有消费成功,后面会重新投递。

所以你的消费逻辑要注意:

text 复制代码
成功就正常返回
失败就抛异常

3)消息堆积是什么?

如果生产者发消息太快,消费者处理太慢,消息就会越积越多。

这叫消息堆积。

比如:

text 复制代码
每秒产生 10000 条消息
每秒只能消费 1000 条消息

剩下的消息就会堆积在 Broker。

解决方式:

text 复制代码
增加消费者实例
优化消费逻辑
增加 Topic 队列数
拆分业务 Topic

24. 面试怎么回答 Topic 和 Group?

你可以这样说:

Topic 是 RocketMQ 中消息的一级分类,生产者发送消息时需要指定 Topic,消费者通过订阅 Topic 来消费消息。

Group 分为 Producer Group 和 Consumer Group。实际开发中更常用的是 Consumer Group,它表示一组消费者实例。

同一个 Consumer Group 内部是竞争消费,一条消息只会被组内一个消费者消费;不同 Consumer Group 之间是独立消费,同一条消息可以被多个不同业务组分别消费。

所以一般不同业务系统使用不同 Consumer Group,同一业务系统的多个实例使用同一个 Consumer Group。

这段可以背下来。


25. 小白最容易记混的点

Topic 不是消费者

Topic 只是消息分类。

text 复制代码
order_topic 不是订单服务
order_topic 是订单消息的分类

Group 不是 Topic 的子分类

Group 表示消费者身份,不是消息分类。

text 复制代码
Topic = 消息是什么
Group = 谁来消费

Tag 才是 Topic 下面的小分类

text 复制代码
Topic = order_topic
Tag = create / cancel / pay / finish

26. 你可以这样记

text 复制代码
Producer:发消息的人
Consumer:收消息的人
Topic:消息大分类
Tag:消息小分类
Group:一组生产者或消费者
Broker:存消息的服务器
NameServer:帮你找 Broker 的地址簿
Queue:Topic 内部的并发队列
Message:真正传递的数据

27. 最后用一句话串起来

比如订单创建成功:

text 复制代码
订单服务作为 Producer,
把一条 order_topic:create 消息发送到 Broker,
Broker 负责保存消息,
库存服务、短信服务、积分服务作为不同 Consumer Group,
分别订阅 order_topic,
收到消息后执行扣库存、发短信、加积分等逻辑。
NameServer 负责告诉生产者和消费者 Broker 在哪里。

你现在先重点记这三个关系就够了:

text 复制代码
Topic:消息分类
Tag:Topic 下的小分类
Consumer Group:消费者分组

以及这句:

text 复制代码
同一个 Group 内部,一条消息只给一个消费者;
不同 Group 之间,同一条消息可以各消费一遍。

这就是 RocketMQ 入门里最核心的东西。

相关推荐
星辰_mya1 小时前
数据同步的几种姿势
大数据·elasticsearch·搜索引擎
子一!!1 小时前
spring基础学习
java·学习·spring
卷毛迷你猪1 小时前
快速实验篇(A5)基于 MapReduce 的降水百分位数计算与干旱等级划分
大数据·mapreduce
Volunteer Technology1 小时前
Flink的DataStream分区操作
大数据·linux·flink
米云科技2 小时前
小红书客服软件支持多账号吗?米多客高效解决跨账号管理难题
大数据·人工智能
呼Lu噜2 小时前
生命周期模型概述(软考教材版)
学习·软件工程
曾阿伦2 小时前
Elasticsearch Analyzer 分析器开发指南
大数据·elasticsearch·搜索引擎
庞白OS2 小时前
一次ds对话
大数据·人工智能
OCR_133716212753 小时前
技术选型干货:通用大模型与垂直OCR模型算力、成本、资源深度对比
大数据·人工智能