RocketMQ源码解析--Broker的读写分离机制

627 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

RockerMQ有两处地方使用到读写分离机制

Broker Master-Slave读写分离

写消息到Master,异步同步到Slave,然后从Slave读取消息。
开启配置为:

slaveReadEnable=True

Broker Direct Memory-Page Cache读写分离

在开启这个机制的时候,写消息会写到Direct Memory,读消息的时候会从操作系统的Page Cache读取。

page cache,又称pcache,其中文名称为页高速缓冲存储器,简称页高缓。page cache的大小为一页,通常为4K。

开启配置为:

transientStorePoolEnable=True

Broker Master-Slave读写分离

这个机制的实现,分为两个步骤:

1 第一步

Broker在处理Pull消息的时候会判断下次是否从slave读取消息。看代码。

long diff = maxOffsetPy - maxPhyOffsetPulling;
long memory = (long) (StoreUtil.TOTAL_PHYSICAL_MEMORY_SIZE
    * (this.messageStoreConfig.getAccessMessageInMemoryMaxRatio() / 100.0));
getResult.setSuggestPullingFromSlave(diff > memory);

maxOffsetPy是当前Master Broker存储的所有消息的最大物理位点
maxPhyOffsetPulling拉取的消息的最大物理位点
diff是两者的差值,那么就是没有消费的消息数量
StoreUtil.TOTAL_PHYSICAL_MEMORY_SIZE是当前Master Broker全部的物理内存大小
this.messageStoreConfig.getAccessMessageInMemoryMaxRatio可以配置,默认是40,也就是说分配百分之40的内存作为Broekr的临界值,当大于这个临界值时,认定Broker处于一个比较繁忙的状态
memory就是Broker临界值下认可使用的内存大小。

在这个前提下,若是diff>memorytrue 那么表示没有拉取的消息占用的内存比认定可以使用的内存大,说明Master节点处于比较繁忙的状态,下一次拉取消息的时候将从Slave节点拉取消息。

public void setSuggestPullingFromSlave(boolean suggestPullingFromSlave) {
    this.suggestPullingFromSlave = suggestPullingFromSlave;
}

判断完之后,给suggestPullingFromSlave赋值,true或者false

也就是说,在每次从Master节点拉取消息的时候,都会判断Broker Master节点的状态,若是Master上尚未读取的消息较多,超过设定的阈值,那么下一次拉取消息的时候,将从Slave节点拉取。

第二步

当消费者Pull消息返回结果的时候,根据上边代码设置的isSuggestPullingFromSlave来判断下一次获取消息的位置。

if (this.brokerController.getBrokerConfig().isSlaveReadEnable() && !this.brokerController.getBrokerConfig().isInBrokerContainer()) {
    if (getMessageResult.isSuggestPullingFromSlave()) {
        responseHeader.setSuggestWhichBrokerId(subscriptionGroupConfig.getWhichBrokerWhenConsumeSlowly());
    }
    else {
        responseHeader.setSuggestWhichBrokerId(subscriptionGroupConfig.getBrokerId());
    }
} else {
    responseHeader.setSuggestWhichBrokerId(MixAll.MASTER_ID);
}

isSlaveReadEnable就是我们设置的配置slaveReadEnable=true isInBrokerContainer是这样解释的,如果是BrokerStartup启动的Broker,就是false,如果是BrokerContainer启动的就是true。 所以这里要求的是BrokerStartup启动的Broker,开启了slaveReadEnable开关,isSuggestPullingFromSlavetrue的时候,下次将从Slave读取消息。 setSuggestWhichBrokerId(1)表示从Slave读取,为0则是从Master读取。

读写分离能很大程度上提高吞吐量,但也会造成数据不一致的风险,