“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情”
broker高并发数据写入
broker消息写入有两种方式,随机写和顺序写。rocketmq在数据写入时会先写到内存中后根据需要同步/异步刷盘到磁盘中。随机写磁盘时需要随机寻址性能没有顺序写高。
broke写入性能优化
(1)CommitLog写入:文件写入时不会直接写到磁盘中,而是先写到OS系统的page cache内存中。这种方式极端情况下会造成数据丢失,如果生产需要数据零丢失可以同步刷盘+磁盘顺序写牺牲性能保证零丢失。
数据丢失场景
第一种情况,Broker(rocketmq就是用java开发出来的中间件系统,启动之后就是一个jvm进程),Broker作为一个jvm进程,突然崩溃掉了,仅仅只是说是一个jvm进程没了而已,page cache里的数据是os管理的,这个场景出现概率比较高一些。
第二种情况,Broker jvm进程所在的服务器,服务器自己本身故障宕机了,os、虚拟机、物理机、硬件层面的故障,此时就会导致你之前写入到page cache里的数据,就会丢失的问题,概率很低,不是说不会发生,机器故障,也是有的,小概率但是会发生,极端情况下数据丢失一定要考虑到位。
page cache内存高并发读写问题
在rocketmq中page cache数据在高并发高吞吐的竞争下可能会出现broker busy异常,broker过于繁忙导致读写操作堵塞。
基于jvm offheap的内存读写分离机制
在rocketmq中开启transientStorePoolEnabled机制,会使用broker管理的offheap(堆外内存),写操作会先写到offheap内存后刷到磁盘中,避免里读写都在page cache中造成读写竞争。使用offheap内存时
,如果broker jvm进程崩溃宕机或者正常关闭brokeroffheap中的数据也会丢失。
Broker写入与读取流程性能优化总结
他的物理存储结构主要是为了优化写入和读取,都是为了写入、存储、读取,这三块去做一个设计的,写入尽可能高吞吐,高并发,如何让存储可以有效的进行数据结构组织服务于我们的写入和读取,如何让高并发的读取可以有效的进行,broker主要要做到的一些事情这样子。
1、写入优化
(1)默认就是直接写入os page cache里,mappedfile机制来实现的,把磁盘文件映射成一块内存,写文件=写内存,就直接返回成功了,内存级的顺序写入,亮点就是基于os page cache来写入数据,如果broker jvm进程崩溃(高概率事件)了,是不会导致os page cache的数据丢失的,服务器崩溃的极端场景才会导致几百毫秒内写入的数据会丢失,一般来说不会发生。
(2)对于ConsumeQueue和IndexFile写入,是异步写入的,这个也是性能提升的一个点,但是只要数据在commit log里没丢失,哪怕是异步写入没有成功,broker jvm就崩溃了,但是broker jvm重启和恢复了,此时基于commit log数据都可以恢复consume queue的数据。
2、存储结构
(1)ConsumeQueue存储结构是经过了极大的优化设计的,物理存储结构设计,极为的精巧的,每个消息在ConsumeQueue里存储的都是定长的(20字节),每个文件是30w个消息,定长,topic目录 -> 多个queue目录 -> 多个磁盘文件,每个磁盘文件一样大的,都是5.72MB
(2)CommitLog他的物理存储结构也是精心设计的,他也是每个文件默认就1GB,满了以后就写下一个文件,文件名,每条消息在所有的commitlog里都有一个总的物理偏移量,每个文件的第一条消息他的总物理偏移量,就是文件的名称,每个commitog他的起始消息的总物理偏移量通过文件名就可以看出来了
3、读取优化
(1)根据消息逻辑offset偏移量(类似于这个queue里第几个消息),定位到你的ConsumeQueue的磁盘文件,在磁盘文件里,就可以去根据你的逻辑上的偏移量,就可以去计算出你的物理偏移量,一次定位,就找到这条消息,就可以找到他在commitlog里的物理偏移量,第二次定位就可以把消息读取出来了
(2)高并发的对page cache进行读写竞争的时候,broker busy,transientStorePool机制,开启之后,就会启用jvm offheap内存,内存级的读写分离