【RocketMQ】7.消息存储 存储介质、RMQ消息存储和发送、消息存储结构、刷盘机制

探讨RocketMQ如何利用磁盘顺序写与零拷贝技术提高消息存储与发送效率,介绍其消息存储结构包括CommitLog和ConsumeQueue,以及同步与异步刷盘机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

消息存储

分布式队列因为有高可靠性的要求,所以数据要进行持久化存储
在这里插入图片描述

  1. 消息生成者发送消息
  2. MQ收到消息,将消息进行持久化,在存储中新增一条记录
  3. 返回ACK给生产者
  4. MQ push 消息给对应的消费者,然后等待消费者返回ACK
  5. 如果消息消费者在指定时间内成功返回ack,那么MQ认为i消息消费成功,在存储中删除消息,即执行第6步;如果MQ在指定时间内没有收到ACK,则认为消息消费失败,会尝试重新push消息,重复执行4.5.6步骤
  6. MQ删除消息
存储介质
  • 关系型数据库DB
    在这里插入图片描述
  • 文件系统
    在这里插入图片描述
性能对比

文件系统>关系型数据库DB

RMQ消息存储和发送
  • 消息存储
    磁盘如果使用得当,磁盘的速度完全可以匹配上网络的数据传输速度。目前的高性能磁盘,顺序写速度可以达到6000MB/s,超过了一般网卡的传输速度。但是磁盘随机写的速度只有大概100kB/s,和顺序写的性能相差6000倍!因为有如此巨大的速度差别,好的消息队列系统会比普通的消息队列速度快多个数量级。RocketMQ的消息用顺序写,保证了消息存储的速度。
  • 消息发送
    Linux操作系统分为【用户态】和【内核态】,文件操作,网络操作需要设计这两种形态的转换,免不了进行数据复制,一台服务器把本机磁盘文件的内容发送到客户端一般分为两个步骤。
  1. read: 读取本的内容
  2. write: 将读取的内容通过网络发送出去

这两个看似简单的操作,实际进行了4次数据复制
在这里插入图片描述
通过使用mmap的方式,可以省区向用户态的内存复制,提高速度,这种机制在Java中是通过MappedByteBuffer实现的RocketMQ充分利用了上述特性,也就是所谓的“零拷贝”技术,提高消息存盘和网络发送的速度。

  • 这里需要注意的是,采用MappedByteBuffer这种内存映射的方式有几个限制,其中之一是一次智能映射1.5G~2G的文件至用户态的虚拟内存,这也是为何RocketMQ默认设置单个
消息存储结构

RocketMQ消息的存储是由ConsumeQueue和CommitLog配合完成的,消息真正的物理存储文件是CommitLog,ConsumeQueue是消息的逻辑队列,类似数据库的索引文件,存储的是指向物理存储的地址。每个Topic下的每个MessageQueue都有一个对应的Consu,eQueue文件。
在这里插入图片描述

  • CommitLog:催你出消息的元数据
  • ConsumerQueue:存储消息在CommitLog的索引
  • IndexFile:为了消息查询提供了一种通过key或事件区间来查询消息的方法,这种通过IndexFile来查找消息的方法不影响发送与消费的主流程。
刷盘机制

RocketMQ的消息是存储到磁盘上的,这样既能保证断电后恢复,又可以让存储的消息量超出内存的限制。RocketMQ为了提高性能,会尽可能地保证磁盘地顺序写。消息在通过Producer写入RocketMQ地时候,有两种写磁盘地方法,分布式同步刷盘和异步刷盘
在这里插入图片描述

  • 同步刷盘
    在返回写成功状态时,消息已经倍写入磁盘,具体流程是,消息写入内存的PAGECACHE后,立刻通知刷盘线程刷盘,然后待刷盘完成,刷盘线程执行完成后唤醒等待的线程,返回消息写成功的状态。
  • 异步刷盘
    在返回写成功状态时,消息可能只是被写入内存的PAGECACHE,写操作的返回快,吞吐量大;当内存里的消息累计到一定程度时,统一触发写磁盘动作,快速写入。
  • 配置
    同步刷盘机制还是异步刷盘,都是通过Brocker配置文件里的flushDiskType参数设置的,这个参数被配置成SYNC_FLUSH,ASYNC_FLUSH中的一个。
<think>好的,用户想了解Spring框架中RocketMQ消息转换机制。首先,我需要回忆一下之前学过的相关知识,尤其是关于Spring Messaging模块RocketMQ整合的内容。记得用户提供的引用中提到RocketMQMessageHandler会构造RocketMQTemplate,并将spring的Message转换为RocketMQ的Message。 首先,我应该从消息转换的基本流程开始。可能需要解释Spring Messaging的MessageRocketMQ的Message结构差异,然后说明转换的步骤。比如,消息头是如何处理的,消息体又是怎么转换的。这里要提到MessageConverter接口,以及默认实现,可能还有用户自定义转换器的部分。 然后,需要引用用户提供的参考内容,特别是引用1引用4中的内容。引用1提到了RocketMQTemplate内部转换消息的过程,而引用4中的代码示例展示了事务消息的处理,可能涉及到消息属性的设置,比如TopicQueueId的变更。这些可以作为具体实现的例子来说明。 接下来,应该分步骤详细说明转换机制。可能包括消息头的映射,比如用户属性如何变成RocketMQ的properties,系统头信息的处理,比如延迟级别。还要提到消息体的序列化方式,比如JSON或者字节数组,以及如何通过MessageConverter进行配置。 另外,用户可能关心如何自定义消息转换,这部分需要说明如何扩展MessageConverter,并注册到Spring容器中。比如,添加FastJson或Protobuf的支持,这里可以举例子说明配置方法。 需要注意文档中的实现类,比如TransactionalMessageServiceImpl中的asyncPrepareMessage方法,将消息的Topic设置为半消息Topic,并存储到CommitLog。这说明在事务消息处理中,消息转换不仅仅是格式转换,还包括属性的修改存储逻辑的变化。 最后,总结整个转换机制的关键点,并确保引用了正确的参考文献。同时,根据用户提供的示例,生成相关的问题,比如性能优化、事务消息处理或者自定义序列化方法。这些问题需要与转换机制紧密相关,帮助用户进一步深入理解。 现在需要检查是否有遗漏的部分,比如消息转换过程中的异常处理,或者不同消息类型(如顺序消息、事务消息)的转换差异。此外,确保所有技术术语使用正确,如RocketMQTemplate、MessageConverter等,并且符合用户提供的引用内容。</think>### Spring框架中RocketMQ消息转换机制实现方式 #### 一、核心实现流程 1. **消息封装阶段** Spring应用通过`RocketMQTemplate`发送消息时,会使用`org.springframework.messaging.Message`封装消息消息体[^1]。例如: ```java Message<String> springMsg = MessageBuilder.withPayload("Hello") .setHeader("TAGS", "demo").build(); ``` 2. **消息转换阶段** `RocketMQTemplate`调用`RocketMQMessageConverter`进行消息转换,关键步骤如下: - **消息头映射**:将Spring Message头转换为RocketMQ Message的`properties`字段 $$properties.put("TAGS", "demo")$$ - **系统头处理**:特殊头信息(如`DELAY`、`KEYS`)会直接设置到RocketMQ Message的对应属性 - **消息体序列化**:默认使用`MappingRocketMQMessageConverter`进行JSON序列化 3. **RocketMQ消息构造** 最终生成`org.apache.rocketmq.common.message.Message`对象: ```java rocketMsg.setTopic("TEST_TOPIC"); rocketMsg.setBody(JSON.toJSONBytes(springMsg.getPayload())); ``` #### 二、关键实现类解析 | 类名 | 职责说明 | 参考代码片段 | |-----------------------------|-----------------------------------|----------------------------------------------------------------------------| | `RocketMQMessageHandler` | 消息处理器入口 | `基于Binding配置构造RocketMQTemplate`[^1] | | `TransactionalMessageServiceImpl` | 事务消息处理 | `message.setTopic(TopicValidator.RMQ_SYS_TRANS_HALF_TOPIC)`[^4] | | `MessageConverter` | 消息格式转换接口 | 支持JSON/byte[]等序列化方式 | #### 三、自定义配置方法 1. **修改序列化方式** 通过配置`RocketMQMessageConverter`实现: ```java @Bean public MessageConverter customConverter() { return new FastJsonRocketMQMessageConverter(); } ``` 2. **扩展消息头映射** 继承`DefaultRocketMQHeaderMapper`类: ```java public class CustomHeaderMapper extends DefaultRocketMQHeaderMapper { @Override public void fromHeaders(...) { // 添加自定义头处理逻辑 } } ``` #### 四、事务消息特殊处理 在事务半消息场景下,消息转换会增加特殊标记: $$message.setProperty("TRAN_MSG", "true")$$ 并通过`TransactionalMessageServiceImpl`将消息暂存到半消息Topic[^4]: ```java // 引用自事务消息处理器 message.setTopic(RMQ_SYS_TRANS_HALF_TOPIC); message.setQueueId(0); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值