0
点赞
收藏
分享

微信扫一扫

RocketMQ架构层面速度快的原因

infgrad 2022-03-15 阅读 34

Broker端相关实现

顺序写CommitLog

RocketMq将所有的消息写入转为顺序写,所有topic的消息顺序写入一个commitLog存储文件。也就是说,仅仅将消息数据追加到文件的末尾,不是在文件的随机位置来修改数据。

刷盘

在Linux实现层面,并非是直接将数据写入磁盘的实现,而是写入Linux操作系统中的os page cache里,也就是仅仅写入内存中,并标记该page cache为脏页,接下来由操作系统自己决定什么时候把os cache里的数据真的刷入(flush)到磁盘文件中。所以写磁盘的操作变为了写内存的操作,性能上得到了提升。

RocketMq通过mmap内存映射技术将磁盘中的commitLog文件映射到内存中

mmap是一种将文件映射到虚拟内存的技术,可以将文件在磁盘位置的地址和在虚拟内存中的虚拟地址通过映射对应起来,之后就可以在内存这块区域进行读写数据,而不必调用系统级别的read,wirte这些函数,从而提升IO操作性能

mq中单个 commitlog 文件,默认大小为 1G,而一个MappedFile即为内存映射中的封装的一个 CommitLog 文件,消息写入时会存在MappedFile的MappdByteBuffer中,在调用force()的时候将数据刷到磁盘中

同步刷盘

每次发送消息,消息都直接存储在 MappedFile 的 mappdByteBuffer,然后直接调用 force() 方法刷写到磁盘,等到 force 刷盘成功后,再返回给调用方(GroupCommitRequest#waitForFlush)就是其同步调用的实现,本质上是使用CountdownLatch来实现的同步等待及唤醒
在这里插入图片描述

异步刷盘

分为两种情况,是否开启堆外内存缓存池,具体配置参数:MessageStoreConfig#transientStorePoolEnable

1)transientStorePoolEnable=false(默认)

消息追加时,直接存入 MappedByteBuffer(pageCache) 中,然后定时 flush,这种很好理解,和同步刷盘相比,只是依赖定时器来定时将MappedByteBuffer中的消息数据刷入磁盘中,流程与同步刷盘差不多

2)transientStorePoolEnable = true
如果设置堆外缓冲池transientStorePoolEnable参数为true,就有点不一样了,之前提到过消息会写入MappedByteBuffer中,也就是pageCache中,而实际上读数据也是读的pageCache,如果读写并发较大,实际也有一定性能影响,mq通过将消息写到堆外内存中来提高性能,实现写消息、读消息读写分离。同时通过堆外缓冲池的使用,也能减少Java堆内存的使用,减少GC压力

开启该参数情况下,消息在追加时,先放入到堆外内存writeBuffer 中,然后定时 commit 到 FileChannel,然后定时flush
在这里插入图片描述

Rocketmq中使用mmap+sendfile机制实现零拷贝

mmap通过虚拟内存映射,让多个虚拟地址指向同一个物理内存地址,用户空间的虚拟地址和内核空间的虚拟地址指向同一个物理内存地址,这样用户空间和内核空间共享同一个内存数据。这样DMA引擎从磁盘上加载的数据不需要在内核空间和用户空间进行复制,减少了一次cpu拷贝

sendfile,指的就是FileChannel.transferTo(long position, long count, WritableByteChannel target)将数据从文件通道传输到了给定的可写字节通道

举报

相关推荐

0 条评论