RocketMQ扫盲(二)broker存储

1、介绍broker

broker应该算是RocketMQ中比较重要的一个环节,负责消息的接收、存储、发送,搭建方式支持主从。实现高性能、高吞吐量。简言之,生产者发送的消息全部到了这里

2、broker与nameserver通信

3、broker存储方式

生产者发给broker消息时先写到内存,再通过线程刷到磁盘。

刷盘机制分为同步和异步两种方式

刷盘配置:

落盘后会有四个文件commitlog 、consumeQueue、IndexFile、checkpoint

4、commitlog

 (1)commitlog文件默认存储在${ROCKET_HOME}/store/commitlog/${fileName}下,文件名是以20个字符长度的00000000000000000000开始,每个文件的大小默认1G =1024*1024*1024 = 1073741824,(第一个文件偏移量从0-107374183,第二个从107374184开始)。如:

(2)创建文件:

//所在文件rocketmq/stroe/Commitlog的putMessage方法

/**
 * 获取最后一个mappedFile文件
 * mappedFile为空,表明${ROCKET_HOME}/store/commitlog目录下不存在任何文件,用偏移量0创建第一个 
 * commit文件,文件为00000000000000000000
 * mappedFile满了,用当前偏移量+文件的sieze生成新的commit文件
*/
if (null == mappedFile || mappedFile.isFull()) {
   mappedFile = this.mappedFileQueue.getLastMappedFile(0); 
}

//如果文件创建失败,抛出异常,可能是磁盘空间不够或权限不够
if (null == mappedFile) {
  log.error("create mapped file1 error, topic: " + msg.getTopic() + " clientAddr: " + msg.getBornHostString());
  beginTimeInLock = 0;
  return new PutMessageResult(PutMessageStatus.CREATE_MAPEDFILE_FAILED, null);
}

(3)commitlog消息格式

(3)commitlog文件的真实存储通过MappedFileQueue的MappedFile来实现,具体可到rocketmq/store/MappedFile 看下

 (4)MappedFile预分配

在消息写入过程中(调用CommitLog的putMessage()方法),CommitLog会先从MappedFileQueue队列中获取一个 MappedFile,
如果没有就新建一个。

这里,MappedFile的创建过程是将构建好的一个AllocateRequest请求(具体做法是,将下一个文件的路径、下下个文件的路径、
文件大小为参数封装为AllocateRequest对象)添加至队列中,后台运行的AllocateMappedFileService服务线程(在Broker启动时,
该线程就会创建并运行),会不停地run,只要请求队列里存在请求,就会去执行MappedFile映射文件的创建和预分配工作,
分配的时候有两种策略,一种是使用Mmap的方式来构建MappedFile实例,另外一种是从TransientStorePool堆外内存池中获取
相应的DirectByteBuffer来构建MappedFile(ps:具体采用哪种策略,也与刷盘的方式有关)。并且,在创建分配完下个MappedFile后,
还会将下下个MappedFile预先创建并保存至请求队列中等待下次获取时直接返回。RocketMQ中预分配MappedFile的设计非常巧妙,
下次获取时候直接返回就可以不用等待MappedFile创建分配所产生的时间延迟。

(5)刷盘或主从同步

//刷盘
handleDiskFlush(result, putMessageResult, msg);
//同步
handleHA(result, putMessageResult, msg);

 

5、consumeQueue

(1)为毛要设计这个东西

RocketMQ的消息都是按照顺序存储,而消费者通常只关心某个Topic下的消息。试想下如果直接从commitlog中查找效率极低,因此可以构建一个索引文件,里面存放着某个Topic下面所有消息在CommitLog中的位置,这样消费者获取消息的时候,只需要先查找这个索引文件,然后再去CommitLog中获取消息就 OK了。(这个类似于mysql的索引)
(2)存储的格式

commitlog offset :存储文件偏移量

size: 消息的长度

hashcode:对消息的topic进行hash,方便消费时对比

一个consumeQueue大概能存30w条目,一个条目20位,300000*20/1000/1000 = 6m左右

0.8481634090231667.png

6、IndexFile

(1)有毛用?

broker除了通过consumeQueue提供给consumer消费之外,还支持通过MsgID或者MessageKey来查询消息;使用ID查询时,因为ID就是用broker+offset生成的(这里msgId指的是服务端的),所以很容易就找到对应的commitLog文件来读取消息。对于用MessageKey来查询消息,MessageStore通过构建一个index来提高读取速度。

(2)结构,重点记下采用hash槽,支持500w的hash槽,2000万的索引条目。

7、checkpoint

记录commitLog、ConsumeQueue、Index文件的刷盘时间点,当上一次broker是异常结束时,会根据StoreCheckpoint的数据进行恢复

8、broker如何提高IO访问性能

主要是通过顺序写、零拷贝。这个等抽空再开篇文章吧

9、参考及鸣谢

https://blog.csdn.net/meilong_whpu/article/details/76919267?utm_source=blogxgwz9

https://www.jianshu.com/p/2c904cc42d95

https://blog.csdn.net/GAMEloft9/article/details/103778895

https://blog.csdn.net/quhongwei_zhanqiu/article/details/39153195

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值