图解MetaQ putMessage部分过程(一)

本文深入剖析了MetaQ在PutMessage时的时序,包括获取可写文件、内存映射、消息追加以及刷盘服务的唤醒。通过解析源码,展示了消息如何封装并追加到内存缓冲区,特别是针对小消息频繁put的优化策略,利用非阻塞计数和并发队列提高效率。后续文章将分享详细代码和测试结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Put消息时序图分析

首先,我们从PutMessage的时序图开始。部分时序图如图1所示。


图1 PutMessage部分时序图

以上部分可以简单理解为以下4步:

1、获取可写入的文件。MapedFileQueue.java中getLastMapedFile()方法;

2、进行内存映射(mmap),将可写文件映射到内存缓冲区。之后应用程序与操作系统共享这块缓冲区。具体原理如下图2所示。

                                        

  图2 mmap原理

参考链接:http://www.penglixun.com/tech/system/linux_cache_discovery.html

       http://www.dongsm.cn/metaq%E9%9B%B6%E6%8B%B7%E8%B4%9D%E6%8A%80%E6%9C%AF%EF%BC%881%EF%BC%89/

        3、向内存缓冲区追加消息。(包括找到追加位置、封装消息、回调追加方法等流程)

        4、追加消息成功之后,唤醒刷盘服务。

源码走读

        1、broker从网络上收到消息并解码之后,开始进行put消息的过程。DefaultMessageStore中putMessage调用如下。

                   

2、获取到可写入文件,并进行内存映射之后,开始向内存缓冲区追加消息。

                   

3、找到追加位置,从内存缓冲区中切分出可写入数据的区域,并由byteBuffer句柄指向这块区域。 

                      

其中mappedByteBuffer即为可写文件在内存中的映射,mappedByteBuffer与byteBuffer的关系如下图。

                     

4、之后,对消息进行一系列的封装,并最终通过调用byteBuffer,put方法,将封装后的消息追加入内存缓冲区。

分析

1、当消息较小,即大量消息小于1k时,每获取到一条小消息,都将进行byteBuffer.put的操作,put操作将被频繁调用。

优化

1、优化思想的核心是减少put的调用,尽量每一次put都写入更多的数据。以下是简化的流程图。

                                 

当新来一个消息,首先判断该消息与队列中已经存在的消息的字节总数(消息体)是否超过4k,如果超过,则将队列中的消息依次进行封装,并将所有的封装后的消息一次性追加入内存缓冲区中。

考虑到并发场景,sizeCount采用单独设计的非阻塞的计数方式,队列采用ConcurrentLinkedQueue。

具体代码还在测试当中,后续文章将整理代码过程及测试结果。。

                            

参考文章:http://hellosure.iteye.com/blog/1126541

               http://www.ibm.com/developerworks/cn/java/j-jtp04186/

               http://www.cnblogs.com/linjiqin/archive/2013/05/30/3108188.html


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值