面试必问RocketMQ物理架构和存储架构

339 阅读6分钟

大纲

  • RocketMQ物理架构
  • Rocket概念模型
  • Rocket支持的各种消息
  • 消息存储结构
  • 过期文件与删除
  • RocketMQ对零拷贝的运用
  • 我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿

1.RocketMQ的物理架构

🍉RocketMQ是阿里巴巴的一款开源产品,性能可以和kafka相媲美,在业务开发领域非常好用。RocketMQ基于发布订阅模型,提供了丰富的功能和多功能消息。 image.png

1.1 NameServer

NameServer是RocketMQ的元数据管理中心、注册中心。所以RocketMQ需要首先启动NameServer,再启动其它的Broker节点。 Broker在启动的时候向所有的NameServer节点注册,Producer在发送消息之前首先向NameServer获取Broker服务地址列表,然后通过一定的负载算法进行消息发送。Consumer消费逻辑也一样。 NameServer与每台Broker服务保持长链接,每30S检查Broker是否存活,如果检测到Broker宕机,则从路由表中踢出。

1.2 Broker

RocketMQ暂存、持久化、传输消息的节点。

1.3 Producer

生产者,负责消息的产生和发送。

1.4 Consumer

消费者,负责对消息的接收和消费。

1.5 Message

消息本身,对于RocketMQ而言,底层就是一个字节数组。

2.Rocket概念模型

2.1 Group

对于生产者而言,分组用来标识同一类消息的Producer,仅做标识使用,没有特别的意义,RocketMQ的生产者Group更多是在事务消息会用到(Broker回查,遇到Producer宕机可以选择Producer同一个组的生产者回查消息是否提交or回滚。) 对于消费者而言,标识一类Consumer的集合。同一个Consumer Group的各个实例将共同消费Topic的消息,可以起到负载均衡的作用。组间共享,组内竞争。 消费进度是以Consumer Group为单元管理,不同的消费者组的消费进度彼此不受影响。

2.2 Topic

标识一类消息的逻辑标识,无论生产者和消费者都要指定Topic。

2.3 Tag

消息的二级分类。

2.4 Message Queue

管理消息的物理单元,一个Topic主题有若干个消息队列,如果一个Topic创建在不同的Broker上,则不同的Broker上都有若干个消息队列。每一个消息队列都对应了一个文件,该文件提供了存储实际消息索引的信息。 Message Queue是一个逻辑无限长的数组,

2.5 Offset

偏移量的概念在RocketMQ中很多,但是一般特Message Queue中的消费偏移量。

3.Rocket支持的各种消息

3.1 消息发送的方式

     - 同步发送:可靠的一种发送方式,需等待消息同步响应后才能成功。
     - 异步发送:异步方式进行消息发送,可通过回调函数来处理失败的业务。
     - 单向发送:Producer只负责发送消息,不负责服务器响应和回调。

3.2 消息的消费方式

     - 集群消费:同一个消息只会分给一个Group消费者组的某一台客户端进行消费。
     - 广播消费:同一个消息会给消费者组里面每一个客户端都投递消息进行消费。

3.3 普通消息

3.4 顺序消息

RocketMQ本身没有提供顺序消息的功能,但是可以借助一个方式来实现消息的顺序性。消息的顺序性分为:全局顺序、局部顺序。 全局顺序:如果生产者和消费者参与的Message Queue只有一个,就能够保证全局顺序性。 局部顺序:如果生产者和消费者参与的Message Queue有多个,只能保证每一个队列里的消息能够顺序消费。

3.5 延时消息

生产者发送某个消息,但是希望一段时间后消费者才能进行消费的情况。RocketMQ开源版只提供了一部分延时时间level选项,ONS商业版支持任意毫秒的延迟消息。

3.6 批量消息

批量发送普通消息,能够提高整体的传输效率,但是最大也不能大于4MB。

3.7 事务消息

image.png 事务消息一共有3个状态:已提交、回滚、中间态(未知)。 RocketMQ的事务消息一般用在分布式事务的最终一致性场景中。

4.RocketMQ消息存储结构

RocketMQ支持消息的持久化,所以对消息可以基于文件进行存储。

4.1 存储文件

     - commitLog:消息存储的目录。
     - config:运行期间的一些配置信息。
     - consumequeue:消息队列的存储目录。
     - index:消息索引文件存储目录。
     - abort:RocketMQ的Broker非正常关闭产生的错误文件。
     - checkpoint:文件检查点,存储commitLog文件最后一次刷盘的时间、consumerqueue最后一次刷盘时间等等。

4.2 消息的存储结构

image.png

4.2.1 CommitLog

CommitLog是以物理文件的方式进行存放,每一台Broker节点上的CommitLog被所有的ConsumerQueue共享。在CommitLog中,每一个消息的长度是不固定的。CommitLog里面不同Topic消息通过磁盘顺序写进行存储。 CommitLog文件大小默认是1GB,也可以支持配置。每台Broker只会往一个CommitLog文件中顺序写,写完一个接着写另一个。 IndexFile和ConsumerQueue都有消息对应的物理偏移量,通过偏移量就可以得到消息的具体在哪个CommitLog中的位置。 CommitLog的特点是:顺序写,随机读。

4.2.2 ConsumeQueue

ConsumeQueue是消息的逻辑队列,存储的是指向物理存储文件的地址。每一个Topic下的每一个Message Queue都有一个对应的ConsumeQueue文件。例如某一个Topic在Broker上有4个MessageQueue,那么这个Topic就会有4个ConsumeQueue文件。 每个ConsumeQueue中存储的消息条目都不是全量数据,而是消息的一部分信息,包括消息在CommitLog中的偏移量、消息大小、消息Tag的哈希值。 当消息存储到CommitLog中后,由后台消息负责构建ConsumeQueue。 单个ConsumeQueue文件最大存储30万个条目。

4.2.3 IndexFile

IndexFile的作用就是提高RocketMQ检索查询消息而设计,RocketMQ支持通过MessageID、MessageKey来查询消息。IndexFile是一个索引文件,底层通过500万个hash槽和冲突链表实现,来做定位查询,一个IndexFile最多2000w条数据。当超过这个数量后就会新建IndexFile。 image.png

5.过期文件删除机制

RocketMQ操作CommitLog、ConsumeQueue是基于内存映射MMAP技术实现的,在Broker启动的时候就会加载这两个目录下的所有文件,所以不可能消息永久性的保存在服务器上。 RocketMQ清除过期文件的方法是:如果某个文件在一定间隔时间内没有被更新,则认为是过期的文件,可以被删除,默认每个文件的过期时间是72小时,可以配置。 RocketMQ触发删除文件的点有:

  - 指定删除文件的时间点,默认是凌晨4点。
  - 发现磁盘空间不足或达到阈值会触发。
  - 手动触发。

6.RocketMQ对MMap的应用

RocketMQ为了提高文件传输的效率采用了mmap技术来实现零拷贝。CommitLog、ConsumeQueue都是通过内存文件映射进行操作。因为使用MappedByteBuffer这种实现有物理大小1.5G~2G的限制,所以单个CommitLog文件大小默认是1GB。