1:为什么创建Topic的时候需要指定MessageQueue的数量
在我们给RocketMq发送消息的时候,首先就是要创建Topic,在创建Topic的时候需要指定一个很关键的参数,就是MeeageQueue, 简单的说就是要指定你这个Topic对应了多少个队列,下图中一个Topic就对应着4个MessageQueue
我们知道每个Topic中的数据都是分布式存储的,也就是说Topic中有一部分数据在Broker1上,有一部分数据在Broker2上
但是我们如何决定将哪些数据放在对应的Broker上呢??所以在这里RocketMq就引入了MessageQueue概念,也就是数据分片机制
假设你现在有1万条数据,然后有二个Broker,4个MessageQueue,每个Broker有二个MessageQueue,这时候大致可以认为每个MessageQueue中有2500条数据,当然这个不是绝对的哈。
那么我们的数据是放到MessageQueue中了,那MessageQueue放在哪呢?? 当然是Broker上
这时候不同的数据都是存储在不同的Broker上的。这也是为什么RocketMq能实现海量数据存储的原理
2:生产者将消息写到哪个MessageQueue中
当我们要发送消息的时候,肯定要从NameServer路由中心去拿到Topic对应的有哪些Broker,拿到Broker也就可以拿到该Topic对应的所有的MessageQueue。这时候只需要根据不同的分法策略将消息发送到不同的MessageQueue就可以了
3:如果某个Broker发生故障了怎么办
如果某个Broker发生了故障,那么基于Dledger和Raft协议就会从多个Slave中进行选举新的Master,这个时候这个Broker是处于不可用的状态,如果这时候我们还往这个Broker发送消息那肯定是发送不成功的
这时候我们可以打开生产者的一个开关,就是sendLatencyFaultEnable,一旦打开这个开关,就会有一个自动容错机制,就是当访问这个Broker的时候超出多少时间还没成功,那么就会隔一段时间不去访问这个Broker,等过一段时间,该Broker节点的主从切换成功之后,就又可以继续访问了
4:Broker是如何持久化数据的
当我们发送一条消息到RocketMq的时候,并不会马上被消费者消息,Broker会首先将该消息写入到一个CommotLog的磁盘文件中,CommitLog是磁盘中的一系列文件,当接收到一条消息之后,就会将这条消息顺序写入到CommitLog文件中,当这个文件大小达到1GB的时候,就会新创建一个CommitLog文件,继续写入消息。
可是我们之前说消息是发送到MessageQueue中的,在这里并没有体现出对MessageQueue的持久化。其实每一个MessageQueue都会对应着一个ConsumeQueue文件,这个ConsumeQueue对应的文件格式如下
$HOME/store/consumequeue/{topic}/{queueId}/{fileName}
我们知道每个Topic都会对应的Broker上的一些MessageQueue
{topic}: 就是对应着哪个topic
{queueId}: 就是就是代表某个Topic下的某个MessageQueue
{fileName}: 就是文件名称了
复制代码
这样说吧,当我们发送一条消息到Broker之后,就会将该消息顺序写入CommitLog这个文件当中。
这时候这个Broker中有二个MessageQueue,分别是MessageQueue0,MessageQueue1,他们分别对应的ConsumeQueue0 , ConsumeQueue1
假设现在Topic是order_topic,那么MessageQueue0和MessageQueue1对应的二个ConsumeQueue对应的文件格式如下:
$HOME/store/consumerqueue/order_topic/messagequeue0/consumequeue0磁盘文件
$HOME/store/consumequeue/order_topic/messagequeue1/consumequeue1磁盘文件
也就是说,当有消息发送到这二个MessageQueue之后,就会将消息写入到CommitLog文件当中,同时也会将这条消息在CommitLog文件中的偏移量和长度还有hashcode等信息存储到对应的ConsumeQueue文件中
也就是说ConsumerQueue中存储的是消息的地址引用
5:如何提升CommitLog的写入性能
RocketMq会将消息写入到CommitLog这个磁盘文件当中,那么如何能够让写入的性能与写入内存的性能一样的??
RocketMq采用了 磁盘顺序写入+ OS PageCache + 异步刷盘机制来实现的
我们知道磁盘顺序写入的性能是比随机写入的性能好的,我们只需要在文件的末尾追加消息就行
RocketMq收到消息并不会直接将消息写入到底层的磁盘文件当中,而是会先写入到OS PageCache的缓存中,然后等待OS的后端线程定时的去执行刷盘操作
6:异步刷盘会有什么问题
现在我们知道RocketMq会将消息写入到OS PageCache的缓存中,然后让OS线程异步的去刷盘,也就是说有些数据还是在缓存中,并没有真正写入到底层磁盘中,如果这时候机器挂了,那么这些在缓存中的数据也是会丢失的。
所以这时候就有了同步刷盘机制。 也就是说RocketMq收到一条消息之后,会同步将这条消息写入到底层磁盘文件当中,然后在返回响应给客户端,这时候除非你硬盘坏了,一般情况下是不会丢失数据的,但是同步刷盘也会导致吞吐量降低,
异步刷盘:吞吐量高,性能好,存在丢失数据的风险
同步刷盘:吞吐量降低,性能较低,保证数据不丢失
复制代码