基础概念

queue=kakfa中的partition
一个Topic的queue中的消息只能被一个消费者组中的一个消费者消费,一个queue中的消息不允洗同一个消费者组中的多个消费者消费。
消费者组中的consumer的数量应该小于等于订阅Topic的queue数量,如果超出Queue数量,则多出来的Consumer将不能消费消息。
一个Topic类型的消息可以被多个消费者组同时消费。
注意:
1)、消费者组只能消费一个Topic消息,不能同时消费多个Topic消息。
2)、一个消费者组中的消费者必须订阅完全相同的Topic。

NameServer

NameServer是一个Broker与Topic路由的注册中心,支持Broker动态注册与发现。
主要包括两个功能:
1、Broker管理:接受Broker集群的注册信息并保存作为路由信息的基本数据,提供心跳检测机制,检查Broker是否还存活。
2、路由信息管理:每个NameServer中都保存着Broker集群中的整个路由信息和用户客户端查询的队列信息。Producer和Conumser通过NameServer可以获取整个Broker集群的路由信息,从而进行消息的投递和消费。

Broker

Broker充当着消息中转角色,负责存储消息,转发消息,Broker在RocketMQ系统重负责接收并存储从生产者发送来的消息,同时为消费者的拉取请求做准备,Broker同时也存储着消息的元数据,包括消费者组消费进度偏移offset、主题、队列等。

consumer获取消息两种方式

拉取消费(Pull)
	consumer主动从Broker中拉取消息,主动权由consumer控制,一旦获取了批量消息,就会启动消费过程,不过该方式实时性较弱,Broker中有了新消息不能及时发现并消费。
推送消费(Push)
	该模式下broker收到数据会主动推送给consumer,该方式实时性较高。是一种典型的发布-订阅模式。即consumer向其关联的queue注册了监听器,一旦发现有新的消息会触发回调执行。会占用较多的系统资源。

消费模式

1、广播消费:给每个consumer发送,offset保存在每个consumer中。
2、集群消费:一条消息只会给某个consumer发送。offset保存在broker集群中。

至少一次原则

RocketMQ有一个原则:每条消息必须至少被成功消费一次。
消费进度记录器
对于广播消费模式,Consumer本身就是消费进度记录器
对于集群模式,Broker是消费进度记录器。
RocketMQ的订阅关系一致性
RocketMQ 的订阅关系一致性,是确保消息系统稳定、可靠、不丢消息、不重复消费的关键
同一个 Group ID 下的所有消费者,订阅的 Topic 和 Tag 必须完全一样
正确的订阅关系:
// 消费者 C1
consumer.subscribe("TopicA", "Tag1||Tag2", listener);

// 消费者 C2
consumer.subscribe("TopicA", "Tag1||Tag2", listener);

// 消费者 C3
consumer.subscribe("TopicA", "Tag1||Tag2", listener);
错误的订阅关系:
	错误示例 1:订阅了不同的 Topic
	C1: consumer.subscribe("TopicA", "*", listener);
	C2: consumer.subscribe("TopicB", "*", listener);
	错误示例 2:订阅了相同的 Topic,但 Tag 不同
	C1: consumer.subscribe("OrderTopic", "PAY||REFUND", listener);
	C2: consumer.subscribe("OrderTopic", "CANCEL", listener);
	错误示例 3:一个订阅了 Tag,一个没订阅
	C1: consumer.subscribe("LogTopic", "ERROR", listener);  // 只处理 ERROR
	C2: consumer.subscribe("LogTopic", "*", listener);       // 处理所有

重试队列

1、由Broker自动创建,名称规则:%RETRY% + Consumer Group ID 是一个特殊的 Topic 名称->%RETRY%{ConsumerGroupName}
2、每个消费者组都有自己独立的重试队列
3、消息进入重试队列后,会按照延迟策略重新投递给消费者
重试机制工作流程
1. 消费者消费消息
   ↓
2. 消费逻辑抛出异常 或 返回 RECONSUME_LATER
   ↓
3. Broker 将消息转发到重试队列:%RETRY%{group}
   ↓
4. 延迟一段时间(指数退避)
   ↓
5. 重试队列的消息再次投递给该消费者组
   ↓
6. 重复尝试,最多 16 次(默认)
   ↓
7. 如果仍失败 → 进入死信队列(%DLQ%)
什么情况下会触发重试?
1、抛出Exception
2、返回 ConsumeConcurrentlyStatus.RECONSUME_LATER
3、消费者宕机(未 ACK)
4、消息超时(长耗时任务)

幂等解决方案

根据业务字段设计订单id,然后从redis/布隆过滤器中查询是否存在,不存在再写入数据库。

生产者给Broker发送消息的三种方式

同步发送:Producer发出消息等待broker的ack,消息可靠性高,性能差
异步发送:Producer发出消息不等待broker的ack,直接发送下一条消息,可靠性可以得到保障,发送效率也可以。
单向发送:Producer仅负责发送消息,不等待、不处理MQ的ack,MQ也不返回ACK,发送效率最高,可靠性最差。

docker运行RocketMQ

1、先启动NameServer。
2、在启动Broker。

posted @ 2025-08-16 22:43  Charlie-Pang  阅读(10)  评论(0)    收藏  举报