【mq读书笔记】mq消息存储

  1. comitlog文件
  2. ConsumerQueue文件
  3. IndexFile文件

RocketMQ将所有主题的消息存储在同一个文件中,确保消息发送时顺序写文件。

为了提高消息消费的效率RocketMQ引入了ConsumeQueue消息队列文件,每个消息主题包含一个多个消息消费队列,每一个消费队列有一个消费文件。消息到达CommitLog文件后,将异步转发到消息消费队列

为了加速消息的检索性能,引入IndexFile索引文件,根据消息的属性快速从Commitlog文件中检索消息。存储消息Key与Offset的对应关系。

  1. messageStoreConfig消息存储配置属性
  2. commitLog文件的存储实现类
  3. consumeQueueTable消息队列缓存列表,按消息主题分组
  4. flushConsumeQueueService消息队列文件ConsumeQueue刷盘线程
  5. cleanCommitLogService清除CommitLog文件服务
  6. cleanConsumeQueueService 清除ConsumeQueue文件服务
  7. indexService 索引文件实现类
  8. allocateMappedFileService MappedFile分配服务
  9. reputMessageService  commitLog消息分发,根据CommitLog文件构建ConsumeQueue,IndexFile。
  10. haService存储HA机制
  11. transientStorePool消息堆内存缓存
  12. MessageArrivingListener 消息拉去长轮询模式达到监听器
  13. brokerConfig。Broker配置属性
  14. storeCheckpoint 文件刷盘检查点
  15. dispatcherList。CommitLog文件转发请求

 

 

 

设置消息存储的时间,如果mappedFile为空表明commitlog目录下不存在任何文件,说明本次消息是第一次消息发送,用偏移量0创建第一个commit文件,如果文件创建失败,抛出CREATE_MAPEDFILE_FAILED,很有可能是磁盘空间不足或权限不够

 

 

msgId=4字节IP+4字节端口号+8字节消息偏移量

 

 

 

消息存储格式(略)

 

 

 

 至此消息已经刷到内存中,返回的结果如下

 

 

若此时将put_ok作为结果返回(异步刷盘,)则客户端收到消息成功的结果之后,服务器宕机没刷到磁盘的消息会丢失。

再看PutMessageResult返回之前的刷盘:

同步刷盘的情况下 会因为等待刷盘超时将PUT_OK更新成FLUSH_DISK_TIMEOUT,默认情况为 ASYNC_FLUSH 修改flushDiskType = SYNC_FLUSH还用同步刷盘。

进一步看下消息主从同步之后的结果:

可以看slave不可用的时候会更新为SLAVE_NOT_AVAILABLE或者FLUSH_NOT_AVAILABLE

此时若master宕机,没有同步到slave的消息就会丢失

默认为 ASYNC_MASTER 修改brokerRole=SYNC_MASTER 改用同步复制。

但是以上都不会再更新AppendMessageResukt,最后返回给客户端都会被认为消息发送成功的

org.apache.rocketmq.broker.processor.SendMessageProcessor#handlePutMessageResult:

再看下客户端producer怎么处理这几种情况的:

可以看到当sendStaus!=OK的时候 会根据设置进行重试,但在重试达到最大次数 默认2,就会直接将结果sendResult返回给业务调用方:

 

 

 综上说书,如果要保证严格的不丢消息的情况:

broker 需要采用如下配置:

同时这个过程我们还需要生产者配合,判断返回状态是否是 SendStatus.SEND_OK。若是其他状态,就需要考虑补偿重试。

虽然上述配置提高消息的高可靠性,但是会降低性能,生产实践中需要综合选择

 

posted @ 2020-01-16 23:56  l2c  阅读(262)  评论(0)    收藏  举报