RocketMQ 系列 系统架构

刨析rocketMQ的底层实现

Posted by lichao modified on September 9, 2021

RocketMQ 基于主题的发布与订阅模式,其核心功能包括消息发送、消息存储(Broker)、消息消费

消息中间件的设计思路一般基于主题的订阅发布机制,消息生产者(Producer)发送某一主题的消息到消息服务器,消息服务器负责该消息的持久化存储,消息消费者(Consumer)订阅感兴趣的主题,消息服务器根据订阅信息(路由信息)将消息推送到消费者(PUSH 模式)或者消息消费者主动向消息服务器拉取消息(PULL 模式),从而实现消息生产者与消息消费者解藕。

功能:

  1. 异步解藕:消息中间件的主要功能是异步解藕,必须具备应对前端的数据洪峰,提高后端系统的可用性,必然要求消息中间件具备一定的消息堆积能力。RocketMQ 消息存储使用磁盘文件(内存映射机制),并且在物理布局上为多个大小相等的文件组成逻辑文件组,可以无限循环使用。RocketMQ 消息存储文件并不是永久存储在消息服务器端,而是提供了过期机制,默认保留7天。
  2. 定时消息:定时消息是指消息发送到Broker后,不能被消息消费端立即消费,要到特定的时间点或者等待特定的时间后才能被消费。如果要支持任意精度的定时消息消费,必须在消息服务端对消息进行排序,势必带来很大的性能损耗,故RocketMQ不支持任意进度的定时消息,而只支持特定延迟级别。
  3. 消息重试机制:消息重试是指消息在消费时,如果发送异常,消息中间件需要支持消息重新投递,RocketMQ 支持消息重试机制。

架构

架构

  • 生产者同一时间,与 NameServer 集群中其中一台建立长连接。
  • 生产者与消费服务器(Broker)之间的 Master 保持长连接。
  • 消费者同一时间与 NameServer 集群中一台建立长连接。
  • 消费者与所有 Broker 建立长连接。

HA-高可用: RocketMQ 4.5 之前的开源版本就是没有 HA 组件的,Master 挂了需要人为干预。然而与其他存储不太一样的是,在生产消息时,消息打到哪台机器,哪个分区(Queue)中其实都是没问题的,只要消费的时候能消费到即可: 比如下图中,节点0挂掉后,客户端只要将消息都路由到节点1就行了(只要不超出负载); ![高可用]](/img/post/mq/rocket/高可用.png){:height=”80%” width=”80%”}

RocketMQ 4.5 版本发布后,可以采用 RocketMQ on DLedger 方式进行部署。RocketMQ on DLedger 基于 Raft协议 进行复制,Master宕机后,Slave会顶上。


存储架构: 架构


整体设计追求简单与性能第一:

  1. NameServer 实现元数据的管理(Topic路由信息等)。 从实际需求出发,因为 Topic 路由信息无须在集群之间保持强一致,追求最终一致性,并且能容忍分钟级的不一致。
  2. 高效的 IO 存储机制. RocketMQ 追求消息发送的高吞吐量,RocketMQ 的消息存储文件设计成文件组的概念,组内单个文件大小固定,方便引人内存映射机制,所有主题的消息存储基于顺序写,极大地提供了消息写性能,同时为了兼顾消息消费与消息查找,引入了消息消费队列文件与索引文件。
  3. 容忍存在设计缺陷,适当将某些工作下放给 RocketMQ 使用者. 保证消息被消费者消费,但设计上允许消息被重复消费,这样极大地简化了消息中间件的内核,使得实现消息发送高可用变得非常简单与高效消息重复问题由消费者在消息消费时实现幕等

问题

RocketMQ 特点

  • 顺序消费:消息消费者按照消息到达消息存储服务器的顺序消费,RocketMQ 可以严格保证消息有序。
  • 消息过滤: 支持在服务端与消费端的消息过滤机制
    • 消息在Broker端过滤,broker只将消息消费者感兴趣的消息发送给消息消费者
    • 消息在消息消费端过滤,消息过滤方式完全由消息消费者自定义
  • RocketMQ 在消息不发生消息堆积时,以长轮询模式实现准实时的消息推送模式。
  • RocketMQ 通过消息消费确认机制(ACK)来确保消息至少被消费一次,但由于ACK 消息有可能丢失等其他原因, RocketMQ 无法做到消息只被消费一次,有重复消费的可能。
  • RocketMQ 支持按时间回溯消息,时间维度可精确到毫秒,可以向前或向后回溯。
  • RocketMQ 支持消息重试机制
  • RocketMQ 不支持任意进度的定时消息,而只支持特定延迟级别。

基本指标

  • 消息堆积能力
  • 消息存储能力

nameServer 相比于 zookeeper 有哪些优势?

nameServer设计极其简单,来实现元数据的管理(topic路由信息等) 取: nameServer集群之间互不通信,极大的降低了nameServer 实现的复杂程度. 舍: topic路由信息无须在集群之间保持强一致,追求最终一致性,并且能容忍分钟级的不一致。

发放为什么为保证可靠性?

Netty 粘包、断包解决?

Rocket 如何提供可宽展性?

RocketMQ 是一个分布式高度可扩展性的消息中间件,

  • broker 扩展性:Broker以集群为单位提供服务。一个集群里有一个master和多个slave.
  • 生产者可扩展性:Producer端,每个实例在发消息的时候,默认会轮询所有的 messageQueue发送,以达到让消息平均落在不同的queue上。而由于queue可以散落在不同的broker,所以消息就发送到不同的broker下.
  • 消费者可扩展性