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左右
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