RocketMq高性能核心原理

消息持久化

RocketMQ消息采用磁盘文件保存消息,默认路径在${user_home}/store目录(可以在broker.conf中自行指定)

主要三个文件

1.CommitLog:存储消息的元数据。所有消息都会顺序存入到CommitLog文件当中。CommitLog由多个文件组成,每个文件固定大小1G。以第一条消息的偏移量为文件名。
2.ConsumerQueue:存储消息在CommitLog的索引。一个MessageQueue一个文件,记录当前MessageQueue被哪些消费者组消费到了哪一条CommitLog。
3.IndexFile:为消息查询提供了一种通过key或时间区间来查询消息的方法,通IndexFile来查找消息的方法不影响发送与消费消息的主流程
 

辅助文件(描述消息的元数据)
checkpoint:数据存盘检查点。里面主要记录commitlog文件、ConsumeQueue文件以及IndexFile文件最后一次刷盘的时间戳。
config/*.json:将RocketMQ的一些关键配置信息进行存盘保存。例如Topic配置、消费者组配置、消费者组消息偏移量Offset 等等一些信息。
abort:RocketMQ用来判断程序是否正常关闭的一个标识文件。正常情况下,会在启动时创
建,而关闭服务时删除。但是如果遇到一些服务器宕机,或者kill -9这样一些非正常关闭服务的情况,这个abort文件就不会删除,因此RocketMQ就可以判断上一次服务是非正常关闭的,后续就会做一些数据恢复的操作。

消息存储结构

待补充

commitLog写入

入口: DefaultMessageStore.asyncPutMess

该方法中会给写入线程加锁,保证一次只会允许一个线程写入。
最终进入CommitLog中的DefaultAppendMessageCallback#doAppend方法,该方法是Broker写入消息的实际
入口。这个方法最终会把消息追加MappedFile映射的一块内存里,并没有直接写入磁盘。而是在随后调用ComitLog#submitFlushRequest方法,提交刷盘申请。刷盘完成之后,内存中的文件才真正写入磁盘中。

提交刷盘申请之后,就会立即调用CommitLog#submitReplicaRequest方法,发起主从同步申请。

文件刷盘

入口:CommitLog.submitFlushRequest
分为同步刷盘和异步刷盘,通过不同的FlushCommitLogService的子服务实现的。

同步刷盘采用的是GroupCommitService子线程。每10毫秒执行一次doCommit方法,扫描文件的缓存。只要缓存当中有消息,就执行一次Flush操作。(不是来一次消息刷一次盘,那么在Broker直接断电的情况接下,就总是会有内存中的消息没有刷入磁盘的情况,这就会造成消息丢失)

异步刷盘采用的是FlushRealTimeService子线程。这个子线程最终也是执行Flush操作,只不过他的执行时机会根据配置进行灵活调整。

异步刷盘和同步刷盘的最本质区别是进行Flush操作的频率不同。最终落地到FileChannel的force方法,该方法会最终调用一次操作系统的fsync系统调用,完成文件写入。

堆外内存使用CommitRealTimeService这个子线程。(通过配置TransientStorePoolEnable参数开启堆外内存),如果开启了堆外内存,会在启动时申请一个跟CommitLog文件大小一致的堆外内存,这部分内存就可以确保不会被交换到虚拟内存中。CommitRealTimeService处理消息的方式则只是调用mappedFileQueue的commit方法。这个方法只是往操作系统的PagedCache里写入消息,并不主动进行刷盘操作。会由操作系统通过Dirty Page机制,在某一个时刻进行统一刷盘。我们在正常关闭操作系统时,经常会等待很⻓时间。这里面大部分的时间其实就是在做PageCache的刷盘。

CommitLog主从复制

入口:CommitLog.submitReplicaRequest
RocketMQ整体是基于Netty实现的网络请求,主从复制使用更轻量级的Java的NIO来构建。

HAService中,会在启动过程中启动三个守护进程

this.acceptSocketService.beginAccept();
this.acceptSocketService.start();
this.groupTransferService.start();
this.haClient.start();

acceptSocketService主要负责维护Master与Slave之间的TCP连接。

groupTransferService主要与主从同步复制有关。

haClient与slave相关。

你可能感兴趣的:(java)