17

RocketMQ 持久化

 4 years ago
source link: http://www.linkedkeeper.com/1641.html?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

RocketMQ 持久化

RocketMQ 持久化
10余年资深架构经验,对高性能网关、多线程、NIO、HTTP/TCP 长连接等技术有较深的研究与实战经验,主导过百亿级网关系统和亿级交易系统的设计与实现,目前主要专注于微服务架构、分布式技术。

RocketMQ 采用文件系统的方式来存储消息,消息的主要存储文件包括 CommitLog 文件、ConsumeQueue 文件、IndexFile 文件。

  • CommitLog 是消息存储的物理文件,所有消息主题的消息都存储在 CommitLog 文件中,每个 Broker 上的 CommitLog 被当前机器上的所有 ConsumeQueue 共享。CommitLog 中的文件默认大小为 1G,可以动态配置; 当一个文件写满以后,会生成一个新的 CommitLog 文件。所有的 Topic 数据是顺序写入在 CommitLog 文件中的。

  • ConsumeQueue 是消息消费的逻辑队列,消息达到 CommitLog 文件后将被异步转发到消息消费队列,供消息消费者消费,这里面包含 MessageQueue 在 CommitLog 中的物理位置偏移量 Offset,消息实体内容的大小和 Message Tag 的 hash 值。每个文件默认大小约为 600W 个字节,如果文件满了后会也会生成一个新的文件。

  • IndexFile 是消息索引文件,Index 索引文件提供了对 CommitLog 进行数据检索,提供了一种通过 key 或者时间区间来查找 CommitLog 中的消息的方法。在物理存储中,文件名是以创建的时间戳明明,固定的单个 IndexFile 大小大概为 400M,一个 IndexFile 可以保存 2000W 个索引。

消息存储的整体结构

linkedkeeper0_f7ed35bd-245f-4912-94ff-23c903a66883.jpg

RocketMQ 的消息存储采用的是混合型的存储结构,也就是 Broker 单个实例下的所有队列公用一个日志数据文件 CommitLog。这个是和 Kafka 又一个不同之处。为什么不采用 Kafka 的设计,针对不同的 Partition 存储一个独立的物理文件呢?这是因为在 Kafka 的设计中,一旦 Kafka 中 Topic 的 Partition 数量过多,队列文件会过多,那么会给磁盘的 IO 读写造成比较大的压力,也就造成了性能瓶颈。所以 RocketMQ 进行了优化,消息主题统一存储在 CommitLog 中。当然它也有它的优缺点。

  • 优点在于:由于消息主题都是通过 CommitLog 来进行读写,ConsumerQueue 中只存储很少的数据,所以队列更加轻量化。对于磁盘的访问是串行化从而避免了磁盘的竞争。

  • 缺点在于:消息写入磁盘虽然是基于顺序写,但是读的过程确是随机的。读取一条消息会先读取 ConsumeQueue,再读 CommitLog,会降低消息读的效率。

消息发送到消息接收的整体流程

1、Producer 将消息发送到 Broker 后,Broker 会采用同步或者异步的方式把消息写入到 CommitLog。RocketMQ 所有的消息都会存放在 CommitLog 中,为了保证消息存储不发生混乱,对 CommitLog 写之前会加锁,同时也可以使得消息能够被顺序写入到 CommitLog,只要消息被持久化到磁盘文件 CommitLog,那么就可以保证 Producer 发送的消息不会丢失。

linkedkeeper0_487cafc4-7bcd-4db4-ab92-e59f802caa0e.jpg

2、CommitLog 持久化后,会把里面的消息 Dispatch 到对应的 Consume Queue 上,Consume Queue 相当于 Kafka 中的 Partition,是一个逻辑队列,存储了这个 Queue 在 CommitLog 中的起始 Offset,log 大小和 MessageTag 的 hashCode。

linkedkeeper0_dbdeaf33-55ff-46f8-9afe-3af542daa8b2.jpg

3、当消费者进行消息消费时,会先读取 ConsumerQueue,逻辑消费队列 ConsumeQueue 保存了指定 Topic 下的队列消息在 CommitLog 中的起始物理偏移量 Offset,消息大小、和消息 Tag 的 HashCode 值。

linkedkeeper0_4cddefc9-5c13-456f-9831-521c5db5998e.jpg

4、直接从 ConsumerQueue 中读取消息是没有数据的,真正的消息主体在 CommitLog 中,所以还需要从 CommitLog 中读取消息。

linkedkeeper0_95105b5c-7df3-4c04-8caf-234e82b37ed4.jpg

Reference

https://blog.csdn.net/Dream__Snow/article/details/88060608

https://www.cnblogs.com/wuzhenzhao/p/11507438.html

https://www.jianshu.com/p/453c6e7ff81c?spm=ata.13261165.0.0.4c9fc4ecEvjsiE


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK