概述
消息消费完成后,需要将消费进度存储起来,即前面提到的offset。广播模式下,同消费组的消费者相互独立,消费进度要单独存储;集群模式下,同一条消息只会被同一个消费组消费一次,消费进度会参与到负载均衡中,故消费进度是需要共享的。
消费进度相关类
OffsetStore
为统一的消费进度接口,定义了操作入口
public interface OffsetStore {
/**
* Load
*/
void load() throws MQClientException;
/**
* Update the offset,store it in memory
*/
void updateOffset(final MessageQueue mq, final long offset, final boolean increaseOnly);
/**
* Get offset from local storage
*
* @return The fetched offset
*/
long readOffset(final MessageQueue mq, final ReadOffsetType type);
/**
* Persist all offsets,may be in local storage or remote name server
*/
void persistAll(final Set<MessageQueue> mqs);
/**
* Persist the offset,may be in local storage or remote name server
*/
void persist(final MessageQueue mq);
/**
* Remove offset
*/
void removeOffset(MessageQueue mq);
/**
* @return The cloned offset table of given topic
*/
Map<MessageQueue, Long> cloneOffsetTable(String topic);
/**
* @param mq
* @param offset
* @param isOneway
*/
void updateConsumeOffsetToBroker(MessageQueue mq, long offset, boolean isOneway) throws RemotingException,
MQBrokerException, InterruptedException, MQClientException;
}
实现类
LocalFileOffsetStore
本地存储消费进度的具体实现,给广播模式使用。
RemoteBrokerOffsetStore
远程存储消费进度的具体实现,给集群模式使用,将消费进度存储在broker。
源码详解
LocalFileOffsetStore将消费进度以固定格式存储在消费者本地文件中,这里不进行具体分析。主要看RemoteBrokerOffsetStore。RemoteBrokerOffsetStore涉及和broker通信,分为消费者端和broker端进行分析。
消费者端
提交offset入口
入口在org.apache.rocketmq.client.impl.consumer.ConsumeMessageConcurrentlyService#processConsumeResult中的最后一段逻辑:
public void processConsumeResult(
final ConsumeConcurrentlyStatus status,
final ConsumeConcurrentlyContext context,
final ConsumeRequest consumeRequest
) {
// 省略
long offset = consumeRequest.getProcessQueue().removeMessage(consumeRequest.getMsgs());
if (offset >= 0 && !consumeRequest.getProcessQueue().isDropped()) {
// 更新offset
this.defaultMQPushConsumerImpl.getOffsetStore().updateOffset(consumeRequest.getMessageQueue(), offset,