19 Broker持久化存储消息的原理

1. Broker的重要性

Broker数据存储实际上才是MQ最核心的环节,它决定了生产者消息写入的吞吐量,决定了消息不能丢失,决定了消费者获取消息的吞吐量。

生产者发送到Broker的消息不可能都放在内存里,一旦机器宕机、重启,就会有消息丢失的问题。所以RocketMQ的Broker是需要将消息持久化到磁盘文件的。

2.Broker持久化消息到磁盘的原理

消息写入磁盘CommitLog文件

生产者发送的消息会直接写入磁盘上的日志文件 CommitLog。

CommitLog包含有很多磁盘文件,每个文件限定最多1GB,Broker收到消息之后就直接追加写入这个文件的末尾。如果一个CommitLog写满了1GB,就会创建一个新的CommitLog文件。

MessageQueue与offset偏移位置

在Broker中,对Topic下的每个MessageQueue会有一系列的ConsumeQueue文件,这些文件落在磁盘上。

ConsumeQueue文件的路径格式:$HOME/store/consumequeue/{topic}/{queueId}/{fileName}.

在上面的ConsumeQueue格式中,{topic}指的是某个Topic,{queueId}指的是某个MessageQueue。而在{fileName}这个文件中,它存储的就是一条消息对应在CommitLog文件中的offset偏移量。(一条消息的内容记录在CommitLog中,这条消息在CommitLog的哪个位置也就是偏移量offset记录在ConsumeQueue文件中)

场景说明:

上图中,Topic下有MessageQueue0和MessageQueue1两个在Broker上,他们分别对应Broker所在机器的磁盘上的ConsumeQueue0和ConsumeQueue1。

假设此时Topic为“TopicOrderPaySuccess”,那么Broker磁盘下的两个路径的文件为:

$HOME/store/consumequeue/TopicOrderPaySuccess/MessageQueue0/ConsumeQueue0磁盘文件
$HOME/store/consumequeue/TopicOrderPaySuccess/MessageQueue1/ConsumeQueue1磁盘文件

如果这时Broker收到一条消息写入了CommitLog之后,它同时会将这条消息在CommitLog中的物理位置,也就是一个文件偏移量,就是一个offset,写入到这条消息所属的MessageQueue对应的ConsumeQueue文件中去。

ConsumeQueue

在ConsumeQueue中存储的每条数据不只是消息在CommitLog中的offset偏移量,还包含了消息的长度,以及tag hashcode,一条数据是20个字节,每个ConsumeQueue文件保存30万条数据,大概每个文件是5.72MB。

3.消息写入CommitLog文件的底层原理

写入CommitLog的高性能

在RocketMQ中,消息写入磁盘CommitLog文件的性能近乎内存写性能。

PageCache和顺序写

Broker是基于OS操作系统的PageCache和顺序写两个机制,来提升写入CommitLog文件的性能的。

首先Broker是以顺序的方式将消息写入CommitLot磁盘文件的,也就是每次写入就是在文件末尾追加一条数据就可以了,对文件进行顺序写的性能要比文件随机写的性能提升很多。

另外,数据写入CommitLog文件的时候,其实不是直接写入底层的物理磁盘文件的,而是先进入OS的PageCache内存缓存中,然后后续由OS的后台线程选一个时间,异步化的将OS PageCache内存缓冲中的数据刷入底层的磁盘文件。

总结:整个优化采用的是 磁盘文件顺序写+OS PageCache写入+OS异步刷盘的策略。

4.异步刷盘与同步刷盘

异步刷盘

上述的模式就是异步刷盘模式,生产者把消息发送个Broker,Broker将消息写入OS PageCache中,就直接返回ACK给生产者了。

存在的弊端:如果生产者认为消息写入成功了,但是实际上那条消息此时是在Broker机器上的os cache中的,如果此时Broker宕机,必然导致这里的数据丢失,而Producer还以为数据已经写入成功了,这就有问题了。

总结:在异步刷盘的策略下,可以让消息写入吞吐量非常高。但是可能会有数据丢失的风险。

同步刷盘

同步刷盘模式下,生产者发送一条消息出去,broker收到了消息,必须直接强制把这个消息刷入底层的物理磁盘文件中,然后才会返回ack给producer,此时生产者才知道消息写入成功了。

如果brokerr还没有来得及把数据同步刷入磁盘,然后他自己挂了,那么此时对producer来说会感知到消息发送失败了,然后你只要不停地重试发送就可以了,直到有slave broker切换成 master broker重新让你可以写入消息,此时可以保证数据是不会丢失的。

同步刷屏的优缺点:如果强制每次消息写入都要直接进入磁盘中,必然导致每条消息写入性能急剧下降,导致消息写入吞吐量急剧下降,但是可以保证数据不会丢失。

5.应用场景

异步刷盘:日志场景,允许部分数据丢失,需要高吞吐

同步刷盘:订单场景,不需要高吞吐,需要保证数据不丢失

补偿机制:库存系统,库存明细可以采用异步刷盘,即使极端情况下数据丢失,也可以通过日志做数据的补偿。

小结:

        生产者将消息发给Broker,Broker将消息写入CommitLog,每个CommitLog最多为1G,写完后,重新建一个。

         每个Topic可以配置多个MessageQueue,每个MessageQueue都对应一系列的ConsumeQueue文件,ConsumeQueue文件中记录的是CommitLog消息的offset偏移量。通过ConsumeQueue中记录的offset偏移量定位到CommitLog中的消息。

        Broker有2中刷盘策略:同步刷盘和异步刷盘。

       同步刷盘是指broker收到消息后,必须强制将消息刷入磁盘,才返回ack给producer;异步刷盘是指broker收到消息后,将消息写入OS PageCache后就返回ack给producer。

       同步刷盘消息写入性能低,但是可以保证消息不丢失;异步刷盘消息写入吞吐量高,但是消息可能会丢失。

       CommitLog采用磁盘顺序写+OS PageCache写入+异步刷盘的方式达到近似内存的写入性能。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值