RocketMq(七):broker是如何将消息读取出来返回给消费机器的呢?消费者是根据什么策略从master或者是slave上拉取消息的呢?commitlog基于os cache+磁盘一起读取机制

前言:

继续深入一下mq,这期主要聊一聊消费者如何获取消息,顺带附带一些上章还未讲完的知识点;

1.broker是如何将消息读取出来返回给消费机器的呢?

涉及两个概念:consumerqueue和commitlog,在上篇文章中,也有讲过,这两个文件,记住是两个文件就完事了,假设一个消费者机器发送拉取请求到broker了,并说:这次要拉取messagequeue0中的消息,如果之前都没拉取过消息,所以就从这个messagequeue0的第一条消息开始拉取,于是broker就会找到messagequeue0对应的consumerqueue0,从里面找到第一条消息的offset,接着broker就需要根据consumequeue0中根据找到第一条消息的地址,然后去commitlog根据这个offset地址去读取这条消息的数据,然后将这条消息数据返回给消费者机器,消费者拉取到一批消息之后,就会回调我们注册的一个函数【贴段代码片段】

consumer.registerMessageListener(new MessageListenerConcurrently(){

@Oberride
public ConsumeConcurrentlyStatus consumeMessage(List<MessageExt> msgs,ConsumeConcurrentlyContext context){
//处理消息
//标记该消息已经成功被消费
return   ConsumeConcurrentlyStatus.CONSUME_SUCCESS
 }
})

再次拉取,broker记录此次消费位置,当处理完这批消息之后,消费者机器会提交目前的消费进度到broker上去,然后broker会存储消费进度,下次这个消费组只要再次拉取这个consumequeue的消息,就直接从broker记录的消费位置开始继续拉取,不用重头拉取了。
【consumer消费broker数据流程图】:
consumer消费broker数据流程图
小总:所以其实消费消息的时候,本质就是根据你需要消费的messagequeue以及消费的位置,去找到的对应的consumequeue读取里面对应位置的消息在commitlog中的物理offset偏移量,然后到commitlog中根据offset读取消息,返回给消费者机器;

2.消费者到底是根据什么策略从master或者是slave上拉取消息的呢?

CommitLog基于os cache提升消息写入性能的,拉取消息的时候,必定会先读取consumeQueue文件,关键的问题:consumequeue会被大量的消费者发送的消息请求给高并发的读取,所以consumequeue文件的读操作是非常频繁的,而且同时极大的影响到消费者进行消息拉取的性能和消费吞吐量,所以实际上broker对consumequeue文件同样也是基于os cache来进行优化的,也就是说,对于broker机器的磁盘上的大量的consumequeue文件,在写入的时候也都是优先进入os cache种的,而且os自己有一个优化机制,就是读取一个磁盘文件的时候,会自动的把磁盘文件的一些数据缓存到os cache中。consumequeue文件主要是存放消息的offset,所以每个文件很小,30万条信息的offset就只有5.72MB而已,所以实际上consumequeue文件是不占用多少磁盘空间的,整体数据很小,几乎可以完全被os缓存在内存的cache中,所以实际上在消费者机器上拉取消息的时候,第一步大量的频繁读取consumequeue文件,几乎可以说就是在内存中读取的性能是一样的,通过这个就可以保证数据消费的高性能的吞吐量
【演变图】

3.commitlog是基于os cache+磁盘一起读取的

在进行消息拉取的时候,先读os cache里的少量consumequeue的数据,这个性能是特别高的,第二部就是根据读取到的offset去commitLog中读取消息的完整数据了,问题:从commitLog中读取消息的完整数据是如何读取的?是从os cache中读取?还是从磁盘中读取?
两者都有:
commitlog是用来存放消息的完整数据的,所以内容量是很大的,毕竟一个文件就要1GB,所以整体完全有可能多达几个TB。所以要思考一下,几个TB的数据,可能都放在os cache中吗?明显就是不可能的,因为os cache用的也是机器的内存,一般多也就是几十个GB而已,更何况broker自身的jvm也要用一些内存,留个os cache的内存知识一部分巴黎,比如10GB-20GB的内存,所以os cache对于commitLog而言,是无法把他全部数据都放在内存中提供读取的。也就是说,os cache对于commitLog而言,主要是提升文件写入性能,当你不停的写入的时候,很多最新写入的数据都会先停留在os cache中,比如这可能就有10GB-20GB的数据,之后os会自动的将cache中比较旧的一些数据输入磁盘中,腾出来空间给更新写入的数据放在os 擦车离,所以大部分数据可能高达几个TB的数据都是在磁盘上的;
【图解】
在这里插入图片描述
结论:当拉取消息的时候,可以轻松的从os cache读取少量的consumequeue文件中的offset,这个新能是极高的,但是去commitLog读取完整消息数据的时候会有两种可能:
第一种可能:如果读取的是刚刚写入commitLog 的数据,大概率还停留在os cache中,此时可以顺利的直接从os cache里读取commit log的数据,这个就是内存读取,性能极佳
第二种可能:读取的是比较早,之前写入commitLog的数据,那些数据早就被刷入磁盘了,已经不在os cache缓存中了,此时就要进入磁盘读取了,这个性能要差一些

4.问题:master broker什么时候会让你从slave broker拉取数据?

假设master broker已经写入了10万条数据,但是现在只是拉取了2万条数据,也就是说还有8万数据是没有被拉取的,master broker是知道机器上当前整体物理内存有多大的,而且他也知道自己可用的最大空间占用比例,因此假设他知道此时自己内存的最多只能放5万条消息,这个时候消费者再过来拉取数据,发现还有8万条消息还未拉取,此时就说明肯定是有3万条消息再磁盘上的,不在os cache中的,会判断消费者有很大概率会从磁盘加载3万条数据,出现这种情况,master broker会认为自己负载太高,导致没有办法将消息及时给消费者,落后进度比较多,这个时候,拉取完消息,就会通知消费者下次从slave broker中去拉取。

这期到此结束,争取知识点比较居中,为了考虑文章的可读性更高,所以就没有设计的非常长偏大论,最后,谢谢大家支持,技术点有误解的地方,希望多多再评论区交流!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咖喱ABC

无需打赏,共同进步学习!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值