RocketMq面试
一、Queue和ConsumeQueue什么关系?
1、Queue(队列) - 逻辑概念
2、ConsumeQueue是物理实现,是磁盘上实实在在的文件,存储在$RocketMQ_HOME/store/consumequeue/{topic}/{queueId}目录下
ConsumeQueue存的是什么?存储内容:每个条目固定20字节,包含:
CommitLog Offset(8字节):消息在CommitLog中的起始物理偏移量
Size(4字节):消息体大小
Message Tag HashCode(8字节):消息标签的哈希值,用于Tag过滤
那么什么时候创建索引ConsumeQueue呢?
首先生产者发送消息:生产者发送消息 --> Broker接收 --> 消息追加到CommitLog末尾 --> 返回成功
2
Broker后台有一个ReputMessageService线程,实时监测CommitLog的新内容。
对于CommitLog中的每条新消息,这个服务会:
1、解析消息,得知它属于哪个Topic的哪个Queue(消息头中有此信息)
2、向对应的ConsumeQueue文件追加一个索引条目(包含CommitLog偏移量等)
3
消费者要消费TopicA-Queue0的消息
–> 查询TopicA-Queue0对应的ConsumeQueue文件
–> 读取索引条目,得到消息在CommitLog中的位置
–> 根据CommitLog偏移量,直接到CommitLog文件中读取真实消息内容
–> 返回给消费者
二、CommitLog里面存的是?
[消息总长度][主题长度][主题名称"OrderTopic"][QueueId=2][其他属性...][消息体"订单消息体"]
三、那么一条消息,保存在CommitLog,怎么体现出他在TopIc下的哪个Queue ?
CommitLog的每条消息,都会记录这条消息属于哪个topic、QueueId,因为根据TopIc和QueueId可以找到属于哪个ConsumeQueue。
[消息总长度][主题长度][主题名称"OrderTopic"][QueueId=2][其他属性…][消息体"订单消息体"]
四、一个Topic中,QueueId和ConsumeQueue是一一对应的?
是的,一个Topic下,QueueId和ConsumeQueue是严格一一对应的关系。
五、消费消息,怎么记录消费到哪?
1、集群模式(CLUSTERING) - 主流模式
在集群模式下,消费进度由Broker集中管理和存储。工作流程:
Consumer消费消息:消费者从Broker拉取一批消息(如20条)进行消费
Consumer处理成功:消费者成功处理完这批消息后
Consumer提交Offset:消费者向Broker发送提交请求,告知"我已处理到第X条"
Broker记录Offset:Broker将进度持久化到磁盘文件consumerOffset.json中
消费记录在Broker端存储,在Broker服务器的磁盘上,Offset信息存储包含:
{"offsetTable": {"TopicA@ConsumerGroupA": {"0": 15678, // TopicA的队列0,消费到第15678条"1": 14233, // TopicA的队列1,消费到第14233条"2": 16891 // TopicA的队列2,消费到第16891条},"TopicB@ConsumerGroupB": {"0": 8921,"1": 7543}}
}
注意:记录中存的是Queue上,不是Consumer,因为Queue和Consumer是对应的,而且Consumer一直会变。
2、广播模式(BROADCASTING)
在广播模式下,每个Consumer实例独立管理自己的消费进度,通常存储在本地文件中。
Consumer本地存储,每个消费者实例在本地文件系统存储:
$USER_HOME/.rocketmq_offsets/{消费者组}/{Broker名称}/{QueueId}/offset.json
