开源消息中间件-Apache RocketMQ


RocketMQ是一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。同时,广泛应用于多个领域,包括异步通信解耦、企业解决方案、金融支付、电信、电子商务、快递物流、广告营销、社交、即时通信、移动应用、手游、视频、物联网、车联网等。采用Java开发并在Apache v2.0协议下授权。

特点
能够保证严格的消息顺序
提供丰富的消息拉取模式
高效的订阅者水平扩展能力
实时的消息订阅机制
亿级消息堆积能力
从Metaq3.0版本开始改名为RocketMQ
发展历程
Metaq 1.x 开源社区维护,因为依赖zk挂了,导致上下游服务全网宕机,到了12年基于开源Kafka,直接用java语言翻译重写。
Metaq 2.x 2012年11月上线,淘宝内部使用。
RocketMQ 3.x 后来一统江湖成为整个阿里系主流MQ。基于公司内部开源共建原则,RocketMQ项目只维护核心功能,且去除了所有其他运行时依赖,核心功能最简化。每个BU的个性化需求都在RocketMQ项目之上进行深度定制。RocketMQ向其他BU提供的仅仅是Jar包,例如要定制一个Broker,那么只需要依赖rocketmq-broker这个jar包即可,可通过API进行交互,如果定制client,则依赖rocketmq-client这个jar包,对其提供的api进行再封装。
RocketMQ 4.x.x 于2016年11月21日捐献给Apache社区,经过不到一年时间重构孵化成为顶级项目。
经历了三代里程碑演进
Notify 为阿里系第一代MQ产品。推模式,数据存储采用关系型数据库。
Metaq 为阿里系第二代MQ产品。拉模式,自研的专有消息存储,在日志处理方面参考Kafka,典型代表MetaQ。
RocketMQ为阿里系第三代MQ产品。以拉模式为主,兼有推模式,低延迟消息引擎RocketMQ,在二代功能特性的基础上,为电商金融领域添加了可靠重试、基于文件存储的分布式事务等特性。使用在了阿里大量的应用上,典型如双11场景,具有万亿级消息堆积能力。
RocketMQ分为开源与商业2个版本:
Apache RocketMQ是对外开源版。
2013年,阿里云ONS(功能相比较更齐全,特别是运维体系完善,例如:运维管控,安全授权,深度培训等纳入商业重中之重)。
2015年,Aliware MQ(Message Queue)是RocketMQ的商业版本,是阿里云商用的专业消息中间件,是企业级互联网架构的核心产品,基于高可用分布式集群技术,搭建了包括发布订阅、消息轨迹、资源统计、定时延时、监控报警等一套完整的消息云服务。
基础概念

Tag
Tag(标签)可以看作子主题,它是消息的第二级类型,用于为用户提供额外的灵活性。使用标签,同一业务模块不同目的的消息就可以用相同 Topic 而不同的 Tag 来标识。比如交易消息又可以分为:交易创建消息、交易完成消息等,一条消息可以没有 Tag 。标签有助于保持你的代码干净和连贯,并且还可以为 RocketMQ 提供的查询系统提供帮助。
Group
RocketMQ 中,订阅者的概念是通过消费组(Consumer Group)来体现的。每个消费组都消费主题中一份完整的消息,不同消费组之间消费进度彼此不受影响,也就是说,一条消息被 Consumer Group1 消费过,也会再给 Consumer Group2 消费。消费组中包含多个消费者,同一个组内的消费者是竞争消费的关系,每个消费者负责消费组内的一部分消息。默认情况,如果一条消息被消费者 Consumer1 消费了,那同组的其他消费者就不会再收到这条消息。
Offset
在 Topic 的消费过程中,由于消息需要被不同的组进行多次消费,所以消费完的消息并不会立即被删除,这就需要 RocketMQ 为每个消费组在每个队列上维护一个消费位置(Consumer Offset),这个位置之前的消息都被消费过,之后的消息都没有被消费过,每成功消费一条消息,消费位置就加一。也可以这么说,Queue 是一个长度无限的数组,Offset 就是下标。
系统架构1

RocketMQ由四部分组成:命名服务器Name Server、代理Broker、生产者Producer和消费者Consumer,其中每一个都可以水平扩展而没有单点故障,如上图所示。
RocketMQ主要由 Producer、Broker、Consumer、Namesvr 等组件组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息,Namesvr负责存储元数据,各组件的主要功能如下:
消息生产者(Producer):负责生产消息,一般由业务系统负责生产消息。一个消息生产者会把业务应用系统里产生的消息发送到Broker服务器。RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送。同步和异步方式均需要Broker返回确认信息,单向发送不需要。
消息消费者(Consumer):负责消费消息,一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。从用户应用的角度而言提供了两种消费形式:拉取式消费、推动式消费。
代理服务器(Broker Server):消息中转角色,负责存储消息、转发消息。代理服务器在RocketMQ系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。代理服务器也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等。
名字服务(Name Server):名称服务充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Namesrv实例组成集群,但相互独立,没有信息交换。
生产者组(Producer Group):同一类Producer的集合,这类Producer发送同一类消息且发送逻辑一致。如果发送的是事务消息且原始生产者在发送之后崩溃,则Broker服务器会联系同一生产者组的其他生产者实例以提交或回溯消费。
消费者组(Consumer Group):同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致。消费者组使得在消息消费方面,实现负载均衡和容错的目标变得非常容易。
RocketMQ整体消息处理逻辑上以Topic维度进行生产消费、物理上会存储到具体的Broker上的某个MessageQueue当中,正因为一个Topic会存在多个Broker节点上的多个MessageQueue,所以自然而然就产生了消息生产消费的负载均衡需求。
命名服务器集群:命名服务器集群是用于服务发现的轻量级组件,它们可用于读取和写入路由信息。每个命名服务器可以记录全局信息,并支持快速存储扩展。
代理集群:代理集群使用轻量级主题topic和队列queue机制来管理数据存储。为了实现容错,代理提供2份或3份数据。客户端可以在Push和Pull模型中获取消息。此外还支持灾难恢复和丰富的指标统计信息。
生产者集群:生产者Producer可以分布式部署,从生产者到代理的消息可以通过多路径进行平衡。此外,还支持快速故障恢复和低延迟。
消费者集群:消费者也可以在Push和Pull模型中进行分布式部署,他们可以实时订阅消息,以集群为单位消费消息,同时还支持消息广播。
系统架构2

RabbitMQ 类似有生产阶段、存储阶段、消费阶段,相较 RabbitMQ 的架构,增加了 NameServer 集群,横向拓展能力较好。参考的 Kafka 做的设计,故也同样拥有 NIO、PageCache、顺序读写、零拷贝的技能,单机的吞吐量在十万级,横向拓展能力较强,官方声明集群下能承载万亿级吞吐。存储阶段可以通过配置可靠性优先的 Broker 参数来避免因为宕机丢消息,简单说就是可靠性优先的场景都应该使用同步。
1、消息只要持久化到 CommitLog(日志文件)中,即使 Broker 宕机,未消费的消息也能重新恢复再消费。
2、Broker 的刷盘机制:同步刷盘和异步刷盘,不管哪种刷盘都可以保证消息一定存储在 Pagecache 中(内存中),但是同步刷盘更可靠,它是 Producer 发送消息后等数据持久化到磁盘之后再返回响应给 Producer。
Broker 通过主从模式来保证高可用,Broker 支持 Master 和 Slave 同步复制、Master 和 Slave 异步复制模式,生产者的消息都是发送给 Master,但是消费既可以从 Master 消费,也可以从 Slave 消费。同步复制模式可以保证即使 Master 宕机,消息肯定在 Slave 中有备份,保证了消息不会丢失。
Consumer 的配置文件中,并不需要设置是从 Master 读还是从 Slave 读,当 Master 不可用或者繁忙的时候, Consumer 的读请求会被自动切换到从 Slave。有了自动切换 Consumer 这种机制,当一个 Master 角色的机器出现故障后,Consumer 仍然可以从 Slave 读取消息,不影响 Consumer 读取消息,这就实现了读的高可用。
如何达到发送端写的高可用性呢?在创建 Topic 的时候,把 Topic 的多个 Message Queue 创建在多个 Broker 组上(相同 Broker 名称,不同 BrokerId 机器组成 Broker 组),这样当 Broker 组的 Master 不可用后,其他组 Master 仍然可用, Producer 仍然可以发送消息。
此架构下的 RocketMQ 不支持把 Slave 自动转成 Master ,如果机器资源不足,需要把 Slave 转成 Master ,则要手动停止 Slave 色的 Broker ,更改配置文件,用新的配置文件启动 Broker。由此,在高可用场景下此问题变得棘手,故需要引入分布式算法的实现,追求 CAP,但实践情况是不能同事满足 CA 的,在互联网场景下较多是在时间 BASE 理论,优先满足 AP,尽可能去满足 C。RocketMQ 引入的是实现 Raft 算法的 Dledger,拥有了选举能力,主从切换,架构拓扑图是这样的:

分布式算法中比较常常听到的是 Paxos 算法,但是由于 Paxos 算法难于理解,且实现比较困难,所以不太受业界欢迎。然后出现新的分布式算法 Raft,其比 Paxos 更容易懂与实现,到如今在实际中运用的也已经很成熟,不同的语言都有对其的实现。Dledger 就是其中一个 Java 语言的实现,其将算法方面的内容全部抽象掉,这样开发人员只需要关系业务即可,大大降低使用难度。
系统定位
是一个队列模型的消息中间件,具有高性能、高可靠、高实时、分布式特点
同时支持Push与Pull方式消费消息
能够保证严格的消息顺序
提供丰富的消息拉取模式
高效的订阅者水平扩展能力
亿级消息堆积能力

四种集群部署方式:
单master (缺点:broker宕机,服务不可用)
多master无slave (缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅)
多master多slave,异步复制 (缺点:Master 宕机,磁盘损坏情况,可能会丢失少量消息)
多master多slave,同步双写(缺点:性能比异步复制模式略低,大约低10%左右)
生产环境部署都是多主多从,下面以2主2从为例:

组件角色
Producer:消息发布的角色,支持分布式集群方式部署。与NameServer(随机)中的其中一个节点建立长链接,定期获取Topic路由信息,并向提供Topic服务的Master建立长链接,另外和 Master之间做心跳。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。
Consumer:消息消费的角色,支持分布式集群方式部署。与NameServer(随机)中的其中一个节点建立长链接,定期获取Topic路由信息,并向提供topic服务的Master、Slave建立长连接 ,由Broker配置订阅规则。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。
NameServer:NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以动态感知Broker的路由的信息。
BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证,为了实现这些功能,Broker包含了以下5个重要子模块:
Remoting Module:整个Broker的实体,负责处理来自clients端的请求。
Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的Topic订阅信息
Store Service:提供方便简单的API接口处理消息存储到物理硬盘和查询功能。
HA Service:高可用服务,提供Master Broker 和 Slave Broker之间的数据同步功能。
Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息的快速查询。
Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。
Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。
NameServer:NameServer是一个非常简单的Topic路由注册中心,支持分布式集群方式部署,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。
BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证,支持分布式集群方式部署。
RocketMQ的Topic的物理分布如图所示:

Topic作为消息生产和消费的逻辑概念,具体的消息存储分布在不同的Broker当中。
Broker中的Queue是Topic对应消息的物理存储单元。
在RocketMQ的整体设计理念当中,消息的生产消费以Topic维度进行,每个Topic会在RocketMQ的集群中的Broker节点创建对应的MessageQueue。
producer生产消息的过程本质上就是选择Topic在Broker的所有的MessageQueue并按照一定的规则选择其中一个进行消息发送,正常情况的策略是轮询。
consumer消费消息的过程本质上就是一个订阅同一个Topic的consumerGroup下的每个consumer按照一定的规则负责Topic下一部分MessageQueue进行消费。
在RocketMQ整个消息的生命周期内,不管是生产消息还是消费消息都会涉及到负载均衡的概念,消息的生成过程中主要涉及到Broker选择的负载均衡,消息的消费过程主要涉及多consumer和多Broker之间的负责均衡。
producer消息生产过程:

producer首先访问namesvr获取路由信息,namesvr存储Topic维度的所有路由信息(包括每个topic在每个Broker的队列分布情况)。
producer解析路由信息生成本地的路由信息,解析Topic在Broker队列信息并转化为本地的消息生产的路由信息。
producer根据本地路由信息向Broker发送消息,选择本地路由中具体的Broker进行消息发送。
consumer消息消费过程:

consumer访问namesvr同步topic对应的路由信息。
consumer在本地解析远程路由信息并保存到本地。
consumer在本地进行Reblance负载均衡确定本节点负责消费的MessageQueue。
consumer访问Broker消费指定的MessageQueue的消息。
事务消息

1).生产者将消息发送至 Apache RocketMQ 服务端。
2).Apache RocketMQ 服务端将消息持久化成功之后,向生产者返回 Ack 确认消息已经发送成功,此时消息被标记为 "暂不能投递",这种状态下的消息即为半事务消息。
3).生产者开始执行本地事务逻辑。
4).生产者根据本地事务执行结果向服务端提交二次确认结果(Commit 或是 Rollback),服务端收到确认结果后处理逻辑如下:
4.1).二次确认结果为 Commit:服务端将半事务消息标记为可投递,并投递给消费者。
4.2).二次确认结果为 Rollback:服务端将回滚事务,不会将半事务消息投递给消费者。
5).在断网或者是生产者应用重启的特殊情况下,若服务端未收到发送者提交的二次确认结果,或服务端收到的二次确认结果为 Unknown 未知状态,经过固定时间后,服务端将对消息生产者即生产者集群中任一生产者实例发起消息回查。说明服务端回查的间隔时间和最大回查次数,请参见 [参数限制]https://rocketmq.apache.org/zh/docs/introduction/03limits/。
6).生产者收到消息回查后,需要检查对应消息的本地事务执行的最终结果。
7).生产者根据检查到的本地事务的最终状态再次提交二次确认,服务端仍按照步骤 4 对半事务消息进行处理。
事务消息生命周期

初始化:半事务消息被生产者构建并完成初始化,待发送到服务端的状态。
事务待提交:半事务消息被发送到服务端,和普通消息不同,并不会直接被服务端持久化,而是会被单独存储到事务存储系统中,等待第二阶段本地事务返回执行结果后再提交。此时消息对下游消费者不可见。
消息回滚:第二阶段如果事务执行结果明确为回滚,服务端会将半事务消息回滚,该事务消息流程终止。
提交待消费:第二阶段如果事务执行结果明确为提交,服务端会将半事务消息重新存储到普通存储系统中,此时消息对下游消费者可见,等待被消费者获取并消费。
消费中:消息被消费者获取,并按照消费者本地的业务逻辑进行处理的过程。此时服务端会等待消费者完成消费并提交消费结果,如果一定时间后没有收到消费者的响应,Apache RocketMQ 会对消息进行重试处理。具体信息,请参见消费重试。
消费提交:消费者完成消费处理,并向服务端提交消费结果,服务端标记当前消息已经被处理(包括消费成功和失败)。Apache RocketMQ 默认支持保留所有消息,此时消息数据并不会立即被删除,只是逻辑标记已消费。消息在保存时间到期或存储空间不足被删除前,消费者仍然可以回溯消息重新消费。
消息删除:Apache RocketMQ 按照消息保存机制滚动清理最早的消息数据,将消息从物理文件中删除。更多信息,请参见消息存储和 [清理机制]https://rocketmq.apache.org/zh/docs/featureBehavior/11messagestorepolicy/。
1.单机支持1万以上持久化队列
顺序写,随机读。consumerQueue是逻辑队列存储元数据信息,commitlog负责存储消息,consumerQueue只存储消息在commitlog中的位置信息,定长存储,支持串行方式刷盘。
2.刷盘策略
同步刷盘
异步刷盘
二者的区别在于是写完PageCache直接返回,还是刷盘后返回。
3.消息查询/消息回溯
支持MessageID和MessageKey查询(业务场景:如某个订单处理失败,是消息没收到还是收到处理出错了)。
按照时间来回溯消息,精度毫秒(业务场景:订单分析,程序bug,导致今天从某个时间点的消息需要重新开始消费)。
4.消息过滤
Broker端(tag的哈希值比对,丢到对应的consumeQueue中) consumer端(直接和tag比)
5.消息获取机制
本质上都是Pull机制(据官方资料显示其中PushConsumer的实时性接近于push)。
PushConsumer:consumer通过长轮询拉取消息后回调MessageListener接口完成消费,业务只需要完成MessageListener完成业务逻辑即可。(注册监听回调,一个线程专门长轮训从broker端拉消息,push到一个本地可配置队列)辑即可。(注册监听回调,一个线程专门长轮训从broker端拉消息,push到一个本地可配置队列)
PullConsumer: 完全由业务系统去控制,定时拉取消息,指定队列消费,主要由业务控制。
6.单队列并行消费
单队列一批消息拉取到消费端,既可以支持单线程串行有序消费,也可以支持多线程乱序消费提高并发性能,如下图所示:

采用滑动窗口方式并行消费,多个线程消费,提交offset都是最小offset。
7.消费负载均衡
都在客户端实现
Producer端:从NameServer获取MessageQueue列表,RR选择具体的消息队列发送消息。

Consumer端: 从NameServer获取MessageQueue列表和其他Consumer状态信息,达到平均消费目的(consumer超过队列数则处于空闲状态)

8.顺序消息原理
在RocketMQ中,主要指的是局部顺序,即一类消息为满足顺序性,必须 Producer 单线程顺序发送,且发送到同一个队列,这样 Consumer 就可以按照 Producer 发送 的顺序去消费消息。
普通顺序消息:Broker重启,队列总数发生变化,导致哈希取模后定位队列变化,导致短暂消息顺序不一致。
严格顺序消息:只要一台机器不可用,整个集群不可用。(同步双写保证)

9.事务支持
RocketMQ采用了2PC的方案来提交事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败的消息,如下图所示:

上图说明了事务消息的大致方案,分为两个逻辑:正常事务消息的发送及提交、事务消息的补偿流程
事务消息发送及提交:
发送消息half消息
服务端响应消息写入结果
根据发送结果执行本地事务如果写入失败,此时half消息对业务不可见,本地逻辑不执行
根据本地事务状态执行Commit或者RollbackCommit操作生成消息索引,消息对消费者可见
补偿流程:
对没有Commit/Rollback的事务消息pending状态的消息,从服务端发起一次“回查”
Producer收到回查消息,检查回查消息对应的本地事务的状态
根据本地事务状态,重新Commit或者Rollback
补偿阶段用于解决消息Commit或者Rollback发生超时或者失败的情况。
10.延时消息
业务场景:支付曾经提过延时消费需求(对应消费失败后,延时多久再推送)
开源版本RocketMQ仅支持定时Level(几个梯度的延时,5s、10s、1min等) 阿里云的ONS支持定时level,以及制定毫秒级别延时时间
11.消息失败重试
Producer端:
Producer 的 send 方法本身支持内部重试,重试逻辑如下:
(1) 至多重试 3 次
(2) 如果发送失败,则轮转到下一个 Broker
(3) 这个方法的总耗时时间不超过 sendMsgTimeout设置的值,默认 10s所以,如果本身向 broker 发送消息产生超时异常,就不会再做重试。 再发送失败由应用层自己做。
Consumer端:
广播模式:发送失败的消息丢弃, 广播模式对于失败重试代价过高,对整个集群性能会有较大影响,失败重试功能交由应用处理 集群模式:将消费失败的消息一条条的发送到broker的重试队列中去,如果此时依然有发送到重试队列还是失败的消息,那就在cosumer的本地线 程
定时5秒钟以后重试重新消费消息,再走一次上面的消费流程。
12.Broker HA机制
同步双写:HA 采用同步双写方式,主备都写成功,向应用返回成功。
异步复制:slave启动一个线程,不断从master拉取commitlog中的数据,然后异步build出ConsumeQueue数据结构。
13.死信队列
由于某些原因消息无法被正确的投递,为了确保消息不会被无故的丢弃,一般将其置于一个特殊角色的队列,这个队列一般称之为死信队列。与此对应的还有一个“回退队列”的概念,试想如果消费者在消费时发生了异常,那么就不会对这一次消费进行确认Ack,进而发生回滚消息的操作之后消息始终会放在队列的顶部,然后不断被处理和回滚,导致队列陷入死循环。为了解决这个问题,可以为每个队列设置一个回退队列,它和死信队列都是为异常的处理提供的一种机制保障。实际情况下,回退队列的角色可以由死信队列和重试队列来扮演。
14.重试队列
重试队列其实可以看成是一种回退队列,具体指消费端消费消息失败时,为防止消息无故丢失而重新将消息回滚到 Broker 中。与回退队列不同的是重试队列一般分成多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大。举个例子:消息第一次消费失败入重试队列 Q1,Q1 的重新投递延迟为 5s,在 5s 过后重新投递该消息;如果消息再次消费失败则入重试队列 Q2,Q2 的重新投递延迟为 10s,在 10s 过后再次投递该消息。以此类推,重试越多次重新投递的时间就越久,为此需要设置一个上限,超过投递次数就入死信队列。重试队列与延迟队列有相同的地方,都是需要设置延迟级别,它们彼此的区别是:延迟队列动作由内部触发,重试队列动作由外部消费端触发;延迟队列作用一次,而重试队列的作用范围会向后传递。
新发展

在过去“分”往往是技术实现的妥协,而现在“合”才是用户的真正需求。RocketMQ 5.0 基于统一 Commitlog 扩展多元化索引,包括时间索引、百万队列索引、事务索引、KV 索引、批量索引、逻辑队列等技术。在场景上同时支撑了 RabbitMQ、Kafka、MQTT、边缘轻量计算等产品能力,努力实现 “消息、事件、流” 的扩展支持,云原生是主流。
不足之处
RocketMQ不管系统架构,还是底层存储都有居多亮点,以此来支撑的众多强大特性,不可否认也有居多不足之处:
没有实现自动感知分配的读写分离策略,只有当master消费性能过低时由RocketMQ决定才会将读请求分摊到slave上;
不支持Master/Slave自动切换。RocketMQ开源版本目前还不支持把Slave自动转成Master,如果机器资源不足,需要把Slave转成Master,则要手动停止Slave角色的Broker,更改配置文件,用新的配置文件启动Broker。商业版本支持自动master/slave主从切换;
不支持数据迁移,对服务扩容不太友好,也不灵活。如果服务需要扩容,只能增加服务器节点数了,然后新增queue分配到新节点上。如果新老机器负载不均衡,要么多增加queue到新机器上,要么替换性能较弱的老旧机器;
不支持多挂载点。当今硬件发展日新月异,pc服务器性能越来越强大,一个物理机器会挂载很块多磁盘,但一个RocketMQ实例却只能读写操作一个挂载点数据,想榨干机器资源,操作多挂载点需要部署多实例或依靠docker容器等来实现。
最新版本:5.0
RocketMQ 5.0 架构概览
项目主页:https://rocketmq.apache.org/

特点
能够保证严格的消息顺序
提供丰富的消息拉取模式
高效的订阅者水平扩展能力
实时的消息订阅机制
亿级消息堆积能力
从Metaq3.0版本开始改名为RocketMQ
发展历程
Metaq 1.x 开源社区维护,因为依赖zk挂了,导致上下游服务全网宕机,到了12年基于开源Kafka,直接用java语言翻译重写。
Metaq 2.x 2012年11月上线,淘宝内部使用。
RocketMQ 3.x 后来一统江湖成为整个阿里系主流MQ。基于公司内部开源共建原则,RocketMQ项目只维护核心功能,且去除了所有其他运行时依赖,核心功能最简化。每个BU的个性化需求都在RocketMQ项目之上进行深度定制。RocketMQ向其他BU提供的仅仅是Jar包,例如要定制一个Broker,那么只需要依赖rocketmq-broker这个jar包即可,可通过API进行交互,如果定制client,则依赖rocketmq-client这个jar包,对其提供的api进行再封装。
RocketMQ 4.x.x 于2016年11月21日捐献给Apache社区,经过不到一年时间重构孵化成为顶级项目。
经历了三代里程碑演进
Notify 为阿里系第一代MQ产品。推模式,数据存储采用关系型数据库。
Metaq 为阿里系第二代MQ产品。拉模式,自研的专有消息存储,在日志处理方面参考Kafka,典型代表MetaQ。
RocketMQ为阿里系第三代MQ产品。以拉模式为主,兼有推模式,低延迟消息引擎RocketMQ,在二代功能特性的基础上,为电商金融领域添加了可靠重试、基于文件存储的分布式事务等特性。使用在了阿里大量的应用上,典型如双11场景,具有万亿级消息堆积能力。
RocketMQ分为开源与商业2个版本:
Apache RocketMQ是对外开源版。
2013年,阿里云ONS(功能相比较更齐全,特别是运维体系完善,例如:运维管控,安全授权,深度培训等纳入商业重中之重)。
2015年,Aliware MQ(Message Queue)是RocketMQ的商业版本,是阿里云商用的专业消息中间件,是企业级互联网架构的核心产品,基于高可用分布式集群技术,搭建了包括发布订阅、消息轨迹、资源统计、定时延时、监控报警等一套完整的消息云服务。
基础概念

Tag
Tag(标签)可以看作子主题,它是消息的第二级类型,用于为用户提供额外的灵活性。使用标签,同一业务模块不同目的的消息就可以用相同 Topic 而不同的 Tag 来标识。比如交易消息又可以分为:交易创建消息、交易完成消息等,一条消息可以没有 Tag 。标签有助于保持你的代码干净和连贯,并且还可以为 RocketMQ 提供的查询系统提供帮助。
Group
RocketMQ 中,订阅者的概念是通过消费组(Consumer Group)来体现的。每个消费组都消费主题中一份完整的消息,不同消费组之间消费进度彼此不受影响,也就是说,一条消息被 Consumer Group1 消费过,也会再给 Consumer Group2 消费。消费组中包含多个消费者,同一个组内的消费者是竞争消费的关系,每个消费者负责消费组内的一部分消息。默认情况,如果一条消息被消费者 Consumer1 消费了,那同组的其他消费者就不会再收到这条消息。
Offset
在 Topic 的消费过程中,由于消息需要被不同的组进行多次消费,所以消费完的消息并不会立即被删除,这就需要 RocketMQ 为每个消费组在每个队列上维护一个消费位置(Consumer Offset),这个位置之前的消息都被消费过,之后的消息都没有被消费过,每成功消费一条消息,消费位置就加一。也可以这么说,Queue 是一个长度无限的数组,Offset 就是下标。
系统架构1

RocketMQ由四部分组成:命名服务器Name Server、代理Broker、生产者Producer和消费者Consumer,其中每一个都可以水平扩展而没有单点故障,如上图所示。
RocketMQ主要由 Producer、Broker、Consumer、Namesvr 等组件组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息,Namesvr负责存储元数据,各组件的主要功能如下:
消息生产者(Producer):负责生产消息,一般由业务系统负责生产消息。一个消息生产者会把业务应用系统里产生的消息发送到Broker服务器。RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送。同步和异步方式均需要Broker返回确认信息,单向发送不需要。
消息消费者(Consumer):负责消费消息,一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。从用户应用的角度而言提供了两种消费形式:拉取式消费、推动式消费。
代理服务器(Broker Server):消息中转角色,负责存储消息、转发消息。代理服务器在RocketMQ系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。代理服务器也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等。
名字服务(Name Server):名称服务充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Namesrv实例组成集群,但相互独立,没有信息交换。
生产者组(Producer Group):同一类Producer的集合,这类Producer发送同一类消息且发送逻辑一致。如果发送的是事务消息且原始生产者在发送之后崩溃,则Broker服务器会联系同一生产者组的其他生产者实例以提交或回溯消费。
消费者组(Consumer Group):同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致。消费者组使得在消息消费方面,实现负载均衡和容错的目标变得非常容易。
RocketMQ整体消息处理逻辑上以Topic维度进行生产消费、物理上会存储到具体的Broker上的某个MessageQueue当中,正因为一个Topic会存在多个Broker节点上的多个MessageQueue,所以自然而然就产生了消息生产消费的负载均衡需求。
命名服务器集群:命名服务器集群是用于服务发现的轻量级组件,它们可用于读取和写入路由信息。每个命名服务器可以记录全局信息,并支持快速存储扩展。
代理集群:代理集群使用轻量级主题topic和队列queue机制来管理数据存储。为了实现容错,代理提供2份或3份数据。客户端可以在Push和Pull模型中获取消息。此外还支持灾难恢复和丰富的指标统计信息。
生产者集群:生产者Producer可以分布式部署,从生产者到代理的消息可以通过多路径进行平衡。此外,还支持快速故障恢复和低延迟。
消费者集群:消费者也可以在Push和Pull模型中进行分布式部署,他们可以实时订阅消息,以集群为单位消费消息,同时还支持消息广播。
系统架构2

RabbitMQ 类似有生产阶段、存储阶段、消费阶段,相较 RabbitMQ 的架构,增加了 NameServer 集群,横向拓展能力较好。参考的 Kafka 做的设计,故也同样拥有 NIO、PageCache、顺序读写、零拷贝的技能,单机的吞吐量在十万级,横向拓展能力较强,官方声明集群下能承载万亿级吞吐。存储阶段可以通过配置可靠性优先的 Broker 参数来避免因为宕机丢消息,简单说就是可靠性优先的场景都应该使用同步。
1、消息只要持久化到 CommitLog(日志文件)中,即使 Broker 宕机,未消费的消息也能重新恢复再消费。
2、Broker 的刷盘机制:同步刷盘和异步刷盘,不管哪种刷盘都可以保证消息一定存储在 Pagecache 中(内存中),但是同步刷盘更可靠,它是 Producer 发送消息后等数据持久化到磁盘之后再返回响应给 Producer。
Broker 通过主从模式来保证高可用,Broker 支持 Master 和 Slave 同步复制、Master 和 Slave 异步复制模式,生产者的消息都是发送给 Master,但是消费既可以从 Master 消费,也可以从 Slave 消费。同步复制模式可以保证即使 Master 宕机,消息肯定在 Slave 中有备份,保证了消息不会丢失。
Consumer 的配置文件中,并不需要设置是从 Master 读还是从 Slave 读,当 Master 不可用或者繁忙的时候, Consumer 的读请求会被自动切换到从 Slave。有了自动切换 Consumer 这种机制,当一个 Master 角色的机器出现故障后,Consumer 仍然可以从 Slave 读取消息,不影响 Consumer 读取消息,这就实现了读的高可用。
如何达到发送端写的高可用性呢?在创建 Topic 的时候,把 Topic 的多个 Message Queue 创建在多个 Broker 组上(相同 Broker 名称,不同 BrokerId 机器组成 Broker 组),这样当 Broker 组的 Master 不可用后,其他组 Master 仍然可用, Producer 仍然可以发送消息。
此架构下的 RocketMQ 不支持把 Slave 自动转成 Master ,如果机器资源不足,需要把 Slave 转成 Master ,则要手动停止 Slave 色的 Broker ,更改配置文件,用新的配置文件启动 Broker。由此,在高可用场景下此问题变得棘手,故需要引入分布式算法的实现,追求 CAP,但实践情况是不能同事满足 CA 的,在互联网场景下较多是在时间 BASE 理论,优先满足 AP,尽可能去满足 C。RocketMQ 引入的是实现 Raft 算法的 Dledger,拥有了选举能力,主从切换,架构拓扑图是这样的:

分布式算法中比较常常听到的是 Paxos 算法,但是由于 Paxos 算法难于理解,且实现比较困难,所以不太受业界欢迎。然后出现新的分布式算法 Raft,其比 Paxos 更容易懂与实现,到如今在实际中运用的也已经很成熟,不同的语言都有对其的实现。Dledger 就是其中一个 Java 语言的实现,其将算法方面的内容全部抽象掉,这样开发人员只需要关系业务即可,大大降低使用难度。
系统定位
是一个队列模型的消息中间件,具有高性能、高可靠、高实时、分布式特点
同时支持Push与Pull方式消费消息
能够保证严格的消息顺序
提供丰富的消息拉取模式
高效的订阅者水平扩展能力
亿级消息堆积能力

四种集群部署方式:
单master (缺点:broker宕机,服务不可用)
多master无slave (缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅)
多master多slave,异步复制 (缺点:Master 宕机,磁盘损坏情况,可能会丢失少量消息)
多master多slave,同步双写(缺点:性能比异步复制模式略低,大约低10%左右)
生产环境部署都是多主多从,下面以2主2从为例:

组件角色
Producer:消息发布的角色,支持分布式集群方式部署。与NameServer(随机)中的其中一个节点建立长链接,定期获取Topic路由信息,并向提供Topic服务的Master建立长链接,另外和 Master之间做心跳。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。
Consumer:消息消费的角色,支持分布式集群方式部署。与NameServer(随机)中的其中一个节点建立长链接,定期获取Topic路由信息,并向提供topic服务的Master、Slave建立长连接 ,由Broker配置订阅规则。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。
NameServer:NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以动态感知Broker的路由的信息。
BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证,为了实现这些功能,Broker包含了以下5个重要子模块:
Remoting Module:整个Broker的实体,负责处理来自clients端的请求。
Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的Topic订阅信息
Store Service:提供方便简单的API接口处理消息存储到物理硬盘和查询功能。
HA Service:高可用服务,提供Master Broker 和 Slave Broker之间的数据同步功能。
Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息的快速查询。
Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。
Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。
NameServer:NameServer是一个非常简单的Topic路由注册中心,支持分布式集群方式部署,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。
BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证,支持分布式集群方式部署。
RocketMQ的Topic的物理分布如图所示:

Topic作为消息生产和消费的逻辑概念,具体的消息存储分布在不同的Broker当中。
Broker中的Queue是Topic对应消息的物理存储单元。
在RocketMQ的整体设计理念当中,消息的生产消费以Topic维度进行,每个Topic会在RocketMQ的集群中的Broker节点创建对应的MessageQueue。
producer生产消息的过程本质上就是选择Topic在Broker的所有的MessageQueue并按照一定的规则选择其中一个进行消息发送,正常情况的策略是轮询。
consumer消费消息的过程本质上就是一个订阅同一个Topic的consumerGroup下的每个consumer按照一定的规则负责Topic下一部分MessageQueue进行消费。
在RocketMQ整个消息的生命周期内,不管是生产消息还是消费消息都会涉及到负载均衡的概念,消息的生成过程中主要涉及到Broker选择的负载均衡,消息的消费过程主要涉及多consumer和多Broker之间的负责均衡。
producer消息生产过程:

producer首先访问namesvr获取路由信息,namesvr存储Topic维度的所有路由信息(包括每个topic在每个Broker的队列分布情况)。
producer解析路由信息生成本地的路由信息,解析Topic在Broker队列信息并转化为本地的消息生产的路由信息。
producer根据本地路由信息向Broker发送消息,选择本地路由中具体的Broker进行消息发送。
consumer消息消费过程:

consumer访问namesvr同步topic对应的路由信息。
consumer在本地解析远程路由信息并保存到本地。
consumer在本地进行Reblance负载均衡确定本节点负责消费的MessageQueue。
consumer访问Broker消费指定的MessageQueue的消息。
事务消息

1).生产者将消息发送至 Apache RocketMQ 服务端。
2).Apache RocketMQ 服务端将消息持久化成功之后,向生产者返回 Ack 确认消息已经发送成功,此时消息被标记为 "暂不能投递",这种状态下的消息即为半事务消息。
3).生产者开始执行本地事务逻辑。
4).生产者根据本地事务执行结果向服务端提交二次确认结果(Commit 或是 Rollback),服务端收到确认结果后处理逻辑如下:
4.1).二次确认结果为 Commit:服务端将半事务消息标记为可投递,并投递给消费者。
4.2).二次确认结果为 Rollback:服务端将回滚事务,不会将半事务消息投递给消费者。
5).在断网或者是生产者应用重启的特殊情况下,若服务端未收到发送者提交的二次确认结果,或服务端收到的二次确认结果为 Unknown 未知状态,经过固定时间后,服务端将对消息生产者即生产者集群中任一生产者实例发起消息回查。说明服务端回查的间隔时间和最大回查次数,请参见 [参数限制]https://rocketmq.apache.org/zh/docs/introduction/03limits/。
6).生产者收到消息回查后,需要检查对应消息的本地事务执行的最终结果。
7).生产者根据检查到的本地事务的最终状态再次提交二次确认,服务端仍按照步骤 4 对半事务消息进行处理。
事务消息生命周期

初始化:半事务消息被生产者构建并完成初始化,待发送到服务端的状态。
事务待提交:半事务消息被发送到服务端,和普通消息不同,并不会直接被服务端持久化,而是会被单独存储到事务存储系统中,等待第二阶段本地事务返回执行结果后再提交。此时消息对下游消费者不可见。
消息回滚:第二阶段如果事务执行结果明确为回滚,服务端会将半事务消息回滚,该事务消息流程终止。
提交待消费:第二阶段如果事务执行结果明确为提交,服务端会将半事务消息重新存储到普通存储系统中,此时消息对下游消费者可见,等待被消费者获取并消费。
消费中:消息被消费者获取,并按照消费者本地的业务逻辑进行处理的过程。此时服务端会等待消费者完成消费并提交消费结果,如果一定时间后没有收到消费者的响应,Apache RocketMQ 会对消息进行重试处理。具体信息,请参见消费重试。
消费提交:消费者完成消费处理,并向服务端提交消费结果,服务端标记当前消息已经被处理(包括消费成功和失败)。Apache RocketMQ 默认支持保留所有消息,此时消息数据并不会立即被删除,只是逻辑标记已消费。消息在保存时间到期或存储空间不足被删除前,消费者仍然可以回溯消息重新消费。
消息删除:Apache RocketMQ 按照消息保存机制滚动清理最早的消息数据,将消息从物理文件中删除。更多信息,请参见消息存储和 [清理机制]https://rocketmq.apache.org/zh/docs/featureBehavior/11messagestorepolicy/。
关键特性
1.单机支持1万以上持久化队列
顺序写,随机读。consumerQueue是逻辑队列存储元数据信息,commitlog负责存储消息,consumerQueue只存储消息在commitlog中的位置信息,定长存储,支持串行方式刷盘。
2.刷盘策略
同步刷盘
异步刷盘
二者的区别在于是写完PageCache直接返回,还是刷盘后返回。
3.消息查询/消息回溯
支持MessageID和MessageKey查询(业务场景:如某个订单处理失败,是消息没收到还是收到处理出错了)。
按照时间来回溯消息,精度毫秒(业务场景:订单分析,程序bug,导致今天从某个时间点的消息需要重新开始消费)。
4.消息过滤
Broker端(tag的哈希值比对,丢到对应的consumeQueue中) consumer端(直接和tag比)
5.消息获取机制
本质上都是Pull机制(据官方资料显示其中PushConsumer的实时性接近于push)。
PushConsumer:consumer通过长轮询拉取消息后回调MessageListener接口完成消费,业务只需要完成MessageListener完成业务逻辑即可。(注册监听回调,一个线程专门长轮训从broker端拉消息,push到一个本地可配置队列)辑即可。(注册监听回调,一个线程专门长轮训从broker端拉消息,push到一个本地可配置队列)
PullConsumer: 完全由业务系统去控制,定时拉取消息,指定队列消费,主要由业务控制。
6.单队列并行消费
单队列一批消息拉取到消费端,既可以支持单线程串行有序消费,也可以支持多线程乱序消费提高并发性能,如下图所示:

采用滑动窗口方式并行消费,多个线程消费,提交offset都是最小offset。
7.消费负载均衡
都在客户端实现
Producer端:从NameServer获取MessageQueue列表,RR选择具体的消息队列发送消息。

Consumer端: 从NameServer获取MessageQueue列表和其他Consumer状态信息,达到平均消费目的(consumer超过队列数则处于空闲状态)

8.顺序消息原理
在RocketMQ中,主要指的是局部顺序,即一类消息为满足顺序性,必须 Producer 单线程顺序发送,且发送到同一个队列,这样 Consumer 就可以按照 Producer 发送 的顺序去消费消息。
普通顺序消息:Broker重启,队列总数发生变化,导致哈希取模后定位队列变化,导致短暂消息顺序不一致。
严格顺序消息:只要一台机器不可用,整个集群不可用。(同步双写保证)

9.事务支持
RocketMQ采用了2PC的方案来提交事务消息,同时增加一个补偿逻辑来处理二阶段超时或者失败的消息,如下图所示:

上图说明了事务消息的大致方案,分为两个逻辑:正常事务消息的发送及提交、事务消息的补偿流程
事务消息发送及提交:
发送消息half消息
服务端响应消息写入结果
根据发送结果执行本地事务如果写入失败,此时half消息对业务不可见,本地逻辑不执行
根据本地事务状态执行Commit或者RollbackCommit操作生成消息索引,消息对消费者可见
补偿流程:
对没有Commit/Rollback的事务消息pending状态的消息,从服务端发起一次“回查”
Producer收到回查消息,检查回查消息对应的本地事务的状态
根据本地事务状态,重新Commit或者Rollback
补偿阶段用于解决消息Commit或者Rollback发生超时或者失败的情况。
10.延时消息
业务场景:支付曾经提过延时消费需求(对应消费失败后,延时多久再推送)
开源版本RocketMQ仅支持定时Level(几个梯度的延时,5s、10s、1min等) 阿里云的ONS支持定时level,以及制定毫秒级别延时时间
11.消息失败重试
Producer端:
Producer 的 send 方法本身支持内部重试,重试逻辑如下:
(1) 至多重试 3 次
(2) 如果发送失败,则轮转到下一个 Broker
(3) 这个方法的总耗时时间不超过 sendMsgTimeout设置的值,默认 10s所以,如果本身向 broker 发送消息产生超时异常,就不会再做重试。 再发送失败由应用层自己做。
Consumer端:
广播模式:发送失败的消息丢弃, 广播模式对于失败重试代价过高,对整个集群性能会有较大影响,失败重试功能交由应用处理 集群模式:将消费失败的消息一条条的发送到broker的重试队列中去,如果此时依然有发送到重试队列还是失败的消息,那就在cosumer的本地线 程
定时5秒钟以后重试重新消费消息,再走一次上面的消费流程。
12.Broker HA机制
同步双写:HA 采用同步双写方式,主备都写成功,向应用返回成功。
异步复制:slave启动一个线程,不断从master拉取commitlog中的数据,然后异步build出ConsumeQueue数据结构。
13.死信队列
由于某些原因消息无法被正确的投递,为了确保消息不会被无故的丢弃,一般将其置于一个特殊角色的队列,这个队列一般称之为死信队列。与此对应的还有一个“回退队列”的概念,试想如果消费者在消费时发生了异常,那么就不会对这一次消费进行确认Ack,进而发生回滚消息的操作之后消息始终会放在队列的顶部,然后不断被处理和回滚,导致队列陷入死循环。为了解决这个问题,可以为每个队列设置一个回退队列,它和死信队列都是为异常的处理提供的一种机制保障。实际情况下,回退队列的角色可以由死信队列和重试队列来扮演。
14.重试队列
重试队列其实可以看成是一种回退队列,具体指消费端消费消息失败时,为防止消息无故丢失而重新将消息回滚到 Broker 中。与回退队列不同的是重试队列一般分成多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大。举个例子:消息第一次消费失败入重试队列 Q1,Q1 的重新投递延迟为 5s,在 5s 过后重新投递该消息;如果消息再次消费失败则入重试队列 Q2,Q2 的重新投递延迟为 10s,在 10s 过后再次投递该消息。以此类推,重试越多次重新投递的时间就越久,为此需要设置一个上限,超过投递次数就入死信队列。重试队列与延迟队列有相同的地方,都是需要设置延迟级别,它们彼此的区别是:延迟队列动作由内部触发,重试队列动作由外部消费端触发;延迟队列作用一次,而重试队列的作用范围会向后传递。
新发展

在过去“分”往往是技术实现的妥协,而现在“合”才是用户的真正需求。RocketMQ 5.0 基于统一 Commitlog 扩展多元化索引,包括时间索引、百万队列索引、事务索引、KV 索引、批量索引、逻辑队列等技术。在场景上同时支撑了 RabbitMQ、Kafka、MQTT、边缘轻量计算等产品能力,努力实现 “消息、事件、流” 的扩展支持,云原生是主流。
不足之处
RocketMQ不管系统架构,还是底层存储都有居多亮点,以此来支撑的众多强大特性,不可否认也有居多不足之处:
没有实现自动感知分配的读写分离策略,只有当master消费性能过低时由RocketMQ决定才会将读请求分摊到slave上;
不支持Master/Slave自动切换。RocketMQ开源版本目前还不支持把Slave自动转成Master,如果机器资源不足,需要把Slave转成Master,则要手动停止Slave角色的Broker,更改配置文件,用新的配置文件启动Broker。商业版本支持自动master/slave主从切换;
不支持数据迁移,对服务扩容不太友好,也不灵活。如果服务需要扩容,只能增加服务器节点数了,然后新增queue分配到新节点上。如果新老机器负载不均衡,要么多增加queue到新机器上,要么替换性能较弱的老旧机器;
不支持多挂载点。当今硬件发展日新月异,pc服务器性能越来越强大,一个物理机器会挂载很块多磁盘,但一个RocketMQ实例却只能读写操作一个挂载点数据,想榨干机器资源,操作多挂载点需要部署多实例或依靠docker容器等来实现。
最新版本:5.0
RocketMQ 5.0 架构概览
项目主页:https://rocketmq.apache.org/