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 入门里最核心的东西。

相关推荐
大大大大晴天1 天前
Hudi技术内幕:RecordPayload到RecordMerger
大数据
SelectDB2 天前
秒级弹性、最高降本 70%:SelectDB Serverless 如何重塑云数仓资源效率
大数据·后端·云原生
WhoAmI2 天前
MapReduce框架原理解析一:InputFormat
大数据·hadoop
WhoAmI2 天前
MapReduce框架原理解析三:OutputFormat
大数据·hadoop
WhoAmI2 天前
MapReduce框架原理解析二:Shuffle
大数据·hadoop
大大大大晴天3 天前
Hudi技术内幕:Key Generation原理与实践
大数据
得物技术6 天前
从埋点需求到规则资产:Hermes Agent 重构得物数仓工作流
大数据·llm·ai编程
久美子6 天前
AI驱动数仓建设的Harness工程实践——本体建模、知识分层与上下文工程
大数据
大树887 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
通信小呆呆7 天前
当算法有了“五感”:多模态数据融合如何向人体感官协同学习?
人工智能·学习·算法·机器学习·机器人