设计理念
RocketMQ 设计基于主题的发布与订阅 模式 , 其核心功能包括消息发送、 消息存储(Broker)、消息消费,整体设计追求简单与性能第一,主要体现在如下三个方面。
摈弃ZK作为信息管理的注册中心
根据CAP原理,zk是追求强一致性的,牺牲可用性。RocketMq自研NameServer来实现元数据的管理(Topic 路由信息等)。从实际需求出发,因为 Topic 路由信息无须在集群之间保持强一致,追求最终一致性,并且能容忍分钟级的不一致。RocketMQ的NameServer集群之间互不通信,极大地降低了NameServer实现的复杂程度, 对网络的要求也降低了不少 ,但是性能相比较 Zookeeper有了极大的提升。
高效IO存储机制
RocketMQ追求消息发送的高吞吐量,RocketMQ的消息存储文件设计成文件组的概念,组内单个文件大小固定,方便引人内存l映射机制,所有主题的消息存储基于顺序写 ,极大地提供了消息写性能,同时为了兼顾消息消 费与消息查找,引入了消息消费队列文件与索引文件。
容忍存在设计缺陷
只保证消息被消 费者消费,但设计上允许消息被重复消费,这样极大地简化了消息中间件的内核,使得实现消息发送高可用变得非常简单高效,消息重复问题由消费者在消息消费时实现幕等。
设计目标
RocketMQ 作为一款消息 中间件 ,需要解决如下问题。
架构模式
RocketMQ 与大部分消息中间件一样,采用发布订阅模式,基本的参与组件主要包括:消息发送者、消息服务器(消息存储)、消息消费、路由发现。
顺序消息
所谓顺序消息,就是消息消费者按照消息达到消息存储服务器的顺序消费。 RocketMQ可以严格保证消息有序。
消息过滤
消息过滤是指在消息消费时,消息消费者可以对同一主题下的消息按照规则 己感兴趣的消息。 RocketMQ消息过滤支持在服务端与消费端的消息过滤机制 。
- 消息在Broker端过滤。Broker只将消息消费者感兴趣的消息发送给消息消费者。
- 消息在消息消费端过滤,消息过滤方式完全 由消息消费者自定义,但缺点是有很多无用的消息会从Broker传输到消费端。
消息存储
消息中间件的 一个核心实现是消息的存储对消息存储一般有如下两个维度的考量 : 消息堆积能力和消息存储性能。
RocketMQ 追求消息存储的高性能,引人内存映射机制,所 有主题的消息顺序存储在同一个文件中 。 同时为了避免消息无限在消息存储服务器中累积,引入了消息文件过期机制与文件存储空间报警机制。
消息高可用性
RocketMQ在同步刷盘机制下可以确保不丢失消息,在异步刷盘模式下会丢失少量消息。
对于单点故障,一旦发生,该节点上的消息全部丢失。
异步复制,可能会丢失少量数据。
同步双写,保证数据不丢失。
消息到达(消费)低延迟
RocketMQ在消息不发生消息堆积时,以长轮询模式实现准实时的消息推送模式。
确保消息必须被消费一次(消息重复)
RocketMQ通过消息消费确认机制(ACK)来确保消息至少被消费一次 ,但由于ACK 消息有可能丢失等其他原因,RocketMQ无法做到消息只被消费一次,有重复消费的可能。
回溯消息
回溯消息是指消息消费端已经消费成功的消息,由于业务要求需要重新消费消息 。 RocketMQ支持按时间回溯消息,时间维度可精确到毫秒,可以向前或向后回溯。
消息堆积
消息中间件的主要功能是异步解锢,必须具备应对前端的数据洪峰,提高后端系统的可用性,必然要求消息中间件具备一定的消息堆积能力。 RocketMQ消息存储使用磁盘文件(内存映射机制),并且在物理布局上为多个大小相等的文件组成逻辑文件组,可以无限循环使用。RocketMQ消息存储文件并不是永久存储在消息服务器端,而是提供了过期机制,默认保留 3天。
定时消息
定时消息是指消息发送到Broker后,不能被消息消费端立即消费,要到特定的时间点或者等待特定的时间后才能被消费。 如果要支持任意精度的定时消息消费,必须在消息服务端对消息进行排序,势必带来很大的性能损耗,故RocketMQ不支持任意进度的定时消息,而只支持特定延迟级别。
消息重试机制
消息重试是指消息在消费时,如果发送异常,消息中间件需要支持消息重新投递,RocketMQ支持消息重试机制。
NameServer

Broker消息服务器在启动时向所有NameServer注册,Producer在发送消 息之前先从NameServer获取 Broker服务器地址列表,然后根据负载算法从列表中选择一台消息服务器进行消息发送。
NameServer与每台Broker服务器保持长连接,并间隔 30s检测Broker是否存活,如果检测到 Broker 宕机 ,则 从路由注册表中将其移除。但是路由变 化不会马上通知消息生产者,为了降低NameServer实现的复杂性 ,在消息发送端提供容错机制来保证消息发送的高可用性。
NameServer本身的高可用可通过部署多台NameServer服务器来实现,但彼此之间互不通信,也就是 NameServer 服务器之间在某一时刻的数据并不会完全相同,但这对消息发送不会造成任何影响。
路由注册
RocketMQ路由注册是通过Broker与NameServer的心跳功能实现的。Broker启动时向集群中所有的NameServer发送心跳语句,每隔30s向集群 中所有NameServer发送心跳包
NameServer收到Broker心跳包时会更新brokerLiveTable缓存中 BrokerLivelnfo的lastUpdateTimestamp ,然后NameServer每隔10s扫描 brokerLiveTable,如果连续120s 没有收到心跳包, NameServer 将移除该 Broker 的路由信息同时关闭 Socket 连接。
路由删除
RocktMQ 有两个触发点来触发路由删除。
- NameServer定时扫描 brokerLiveTable 检测上次心跳包与当前系统时间的时间差, 如果时间戳大于120s ,则需要移除该Broker信息。
- Broker 在正常被关闭的情况下,发送命令到NameServer。
路由发现
RocketMQ 路由发现是非实时的,当Topic 路由出现变化后, NameServer不主动推送给客户端 , 而是由客户端定时拉取主题最新的路由。
