type
status
date
slug
summary
tags
category
icon
password
RocketMQ面试题
消息模型
- 队列模型:一个队列可以存储多个生产者的消息,一个队列也可以有多个消费者,但是消费者之间是竞争关系,也就是说每条消息只能被一个消费者消费
- 发布/订阅模型:消息的发送方称为发布者(Publisher),消息的接收方称为订阅者(Subscriber),服务端存放消息的容器称为主题(Topic)。发布者将消息发送到主题中,订阅者在接收消息之前需要先“订阅主题”。每份订阅中,订阅者都可以接收到主题的所有消息
消费模式
- 集群消费:一个消费者组共同消费一个主题的多个队列,一个队列只会被一个消费者消费,如果某个消费者挂掉,分组内其它消费者会接替挂掉的消费者继续消费
- 广播消费:消息会发给消费者组中的每一个消费者进行消费
RocketMQ架构

NameServer
一个无状态的服务器,和broker保持长连接,维护Topic的路由信息
Broker
消息存储和中转角色,负责存储和转发消息,内部维护着多个Consumer Queue,用来存储消息的索引,真正存储消息的地方是 CommitLog(日志文件),与NameServer保持长连接和心跳,定时向其同步Topic信息
Producer
消息生产者,消息通过多种负载均衡模式发送到Broker集群,发送低延时,支持快速失败,有三种发送消息的方式:同步、异步和单向
Consumer
消息消费者,支持PUSH和PULL两种消费模式,支持集群消费和广播消费,提供实时的消息订阅机制。
Pull:拉取型消费者(Pull Consumer)主动从消息服务器拉取信息,只要批量拉取到消息,用户应用就会启动消费过程,所以Pull称为主动消费型
Push:推送型消费者(Push Consumer)封装了消息的拉取、消费进度和其他的内部维护工作,将消息到达时执行的回调接口留给用户应用程序来实现。所以 Push 称为被动消费类型,但其实从实现上看还是从消息服务器中拉取消息,不同于 Pull 的是 Push 首先要注册消费监听器,当监听器处触发后才开始消费消息
如何保证消息不丢失
生产阶段
主要通过请求确认机制,来保证消息的可靠传递
存储阶段
通过配置可靠性优先的Broker参数来避免因为宕机丢消息
消费阶段
在执行完所有消费逻辑后发送消费确认,消息队列维护了消费的位置,逻辑执行失败了,没有确认,再去队列拉取消息,就还是之前的一条
如何保证消息的幂等性
- 消息必须携带业务唯一标识,可以通过雪花算法生成全局唯一ID
- 在消费者接收到消息后,判断 Redis 中是否存在该业务主键的标志位,若存在标志位,则认为消费成功,否则执行业务逻辑,执行完成后,在缓存中添加标志位
- 利用数据库的唯一索引来防止业务的重复插入
- 在数据库表中使用版本号,通过乐观锁机制来保证幂等性。每次更新操作时检查版本号是否一致,只有一致时才执行更新并递增版本号。如果版本号不一致,则说明操作已被执行过,拒绝重复操作
如何处理消息堆积
- 消费者扩容:如果当前 Topic 的 Message Queue 的数量大于消费者数量,就可以对消费者进行扩容,增加消费者,来提高消费能力,尽快把积压的消息消费完
- 消息迁移 Queue 扩容:如果当前 Topic 的 Message Queue 的数量小于或者等于消费者数量,这种情况,再扩容消费者就没什么用,就得考虑扩容 Message Queue。可以新建一个临时的 Topic,临时的 Topic 多设置一些 Message Queue,然后先用一些消费者把消费的数据丢到临时的 Topic,因为不用业务处理,只是转发一下消息,还是很快的。接下来用扩容的消费者去消费新的 Topic 里的数据,消费完了之后,恢复原状
顺序消息
局部顺序消息
保证在某个逻辑分区或业务逻辑下的消息顺序。
分区策略:将消息根据某个关键字段进行哈希分区,确保同一关键字段的消息总是发送到同一个分区
顺序队列:在消息队列中为每个业务逻辑创建一个独立的队列,确保同一业务逻辑的消息按顺序处理
全局顺序消息
保证消息在整个系统范围内的严格顺序,即消息按照生产的顺序被消费
单一队列:将所有消息发送到一个单一的队列中,确保消息按顺序处理
消息过滤
- 在 Broker 端按照 Consumer 的去重逻辑进行过滤,这样做的好处是避免了无用的消息传输到 Consumer 端,缺点是加重了Broker的负担,实现起来相对复杂。
- 在 Consumer 端过滤,比如按照消息设置的 tag 去重,这样的好处是实现起来简单,缺点是有大量无用的消息到达了Consume端只能丢弃不处理
Tag过滤
SQL表达式过滤
Filter Server过滤
最灵活,也是最复杂的一种方式,允许用户自定义函数进行过滤
RocketMq延时消息
Broker收到延时消息了,会先发送到主题(SCHEDULE_TOPIC_XXXX)的相应时间段的 Message Queue 中,然后通过一个定时任务轮询这些队列,到期后,把消息投递到目标 Topic 的队列中,然后消费者就可以正常消费这些消息
死信队列
消费者在处理消息时发生异常,且达到了最大重试次数

- 作者:JackJame
- 链接:https://notion.qjit1314.eu.org/article/example-15
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。


