rebalance,collaborator

xwhxwh 阅读:122 2022-03-29 09:44:42 评论:0
Rocket MQ 的前世与今生

RocketMQ是⼀款阿⾥巴巴开源的消息中间件rebalance,在2017年9⽉份成为Apache的顶级项⽬,是国内⾸个互联⽹中间件在 Apache 上的顶级项⽬。

rebalance

RocketMQ经历了4个大阶段(如上图):

阶段1:Metaq(Metamorphosis) 1.x 由开源社区 killme2008 维护,最后⼀次更新是在2017年1⽉份。

阶段2:Metaq 2.x 于 2012 年 10 ⽉份上线,在淘宝内部被⼴泛使⽤。

阶段3:RocketMQ 3.x 基于阿⾥内部开源共建原则, RocketMQ 项⽬只维护核⼼功能,且去除了所有其他运⾏时依赖, 核⼼功能最简化。每个 BU 的个性化需求都在 RocketMQ 项⽬之上进⾏深度定制。 RocketMQ 向其他 BU 提供的仅仅是Jar 包,例如要定制⼀个 Broker,那么只需要依赖 rocketmq-broker 这个 jar 包即 可,可通过 API 迕⾏交互,如果定制 client,则依赖 rocketmq-client 这个 jar 包,对其提供的 api 进⾏ 再封装。

阶段4:进⼊Apache 2016年11⽉28⽇,阿⾥巴巴向 Apache 软件基⾦会捐赠消息中间件 RocketMQ,成为 Apache 孵 化项⽬。美国时间 2017 年 9 ⽉ 25 ⽇,Apache 软件基⾦会(ASF)宣布 Apache®RocketMQ™ 已孵化 成为 Apache 顶级项⽬(TLP ),是国内⾸个互联⽹中间件在 Apache 上的顶级项⽬。

各种MQ产品的比较

rebalance

此处比较并没有列出ActivateMQ,因为ActivateMQ目前使用占额已经越老越小,所以此次 不再拿出来进行比较。

功能对比:

rebalance

总结:

Kafka:系统间的数据流通道RocketMQ:⾼性能可靠消息传输RabbitMQ:低延迟可靠性传输使用场景

1.异步解耦

场景:用户注册后,需要发送注册邮件和短信通知,以告知用户注册成功rebalance;传统的做法有以下两种。

串行方式:

rebalance

并行方式:

rebalance

MQ解耦:

rebalance

总结:从三种实现方式可以看出,使用MQ进行异步解耦能让服务的功能变得更单一、更高效,明确功能的主次。

2.削峰填谷

场景:在秒杀或团队抢购活动中,由于用户请求量较大,导致流量暴增,秒杀的应用在处理如此大量的访问流量后,下游的通知系统无法承载海量的调用量,甚至会导致系统崩溃等问题而发生漏通知的情况。

rebalance

总结:在互联网开发过程中突发大流量情况非常多,也有很多成熟的解决方案,使用MQ来进行削峰填谷也是业界比较成熟的一个方案。

3.数据同步与check

场景:订单数据存储为分片数据库,不利于聚合查询和批量操作,利用binlog将数据同步到MQ中,业务消费MQ对数据加工处理,可以将数据同步到其它存储系统,也可以做数据Check等

rebalance

总结:采用订阅Binlog方式,将数据打进MQ进行临时存储,其它服务可以通过订阅MQ进行处理自己的业务,比如数据同步、数据一致性检查待。

4.其它场景

当然MQ还有其它一些使用场景,在这里就不在一一介绍了,具体如下:

顺序收发分布式事务⼀致性⼤数据分析分布式缓存同步

这些使用场景可以说是MQ的优点,但是同样也会带来一些问题:

使用MQ后的缺点:

1)系统更复杂,多了一个MQ组件

2)消息传递路径更长,延时会增加

3)消息可靠性和重复性互为矛盾,消息不丢不重难以同时保证

4)上游无法知道下游的执行结果,这一点是很致命的

架构原理

基本概念(来自官网)

1.消息模型(Message Model)

RocketMQ主要由 Producer、Broker、Consumer 三部分组成,其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。Broker 在实际部署过程中对应一台服务器,每个 Broker 可以存储多个Topic的消息,每个Topic的消息也可以分片存储于不同的 Broker。Message Queue 用于存储消息的物理地址,每个Topic中的消息地址存储于多个 Message Queue 中。ConsumerGroup 由多个Consumer 实例构成。

2 消息生产者(Producer)

负责生产消息,一般由业务系统负责生产消息。一个消息生产者会把业务应用系统里产生的消息发送到broker服务器。RocketMQ提供多种发送方式,同步发送、异步发送、顺序发送、单向发送。同步和异步方式均需要Broker返回确认信息,单向发送不需要。

3 消息消费者(Consumer)

负责消费消息,一般是后台系统负责异步消费。一个消息消费者会从Broker服务器拉取消息、并将其提供给应用程序。从用户应用的角度而言提供了两种消费形式:拉取式消费、推动式消费。

4 主题(Topic)

表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题,是RocketMQ进行消息订阅的基本单位。

5 代理服务器(Broker Server)

消息中转角色,负责存储消息、转发消息。代理服务器在RocketMQ系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。代理服务器也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等。

6 名字服务(Name Server)

名称服务充当路由消息的提供者。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Namesrv实例组成集群,但相互独立,没有信息交换。

7 拉取式消费(Pull Consumer)

Consumer消费的一种类型,应用通常主动调用Consumer的拉消息方法从Broker服务器拉消息、主动权由应用控制。一旦获取了批量消息,应用就会启动消费过程。

8 推动式消费(Push Consumer)

Consumer消费的一种类型,该模式下Broker收到数据后会主动推送给消费端,该消费模式一般实时性较高。

9 生产者组(Producer Group)

同一类Producer的集合,这类Producer发送同一类消息且发送逻辑一致。如果发送的是事务消息且原始生产者在发送之后崩溃,则Broker服务器会联系同一生产者组的其他生产者实例以提交或回溯消费。

10 消费者组(Consumer Group)

同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致。消费者组使得在消息消费方面,实现负载均衡和容错的目标变得非常容易。要注意的是,消费者组的消费者实例必须订阅完全相同的Topic。RocketMQ 支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting)。

11 集群消费(Clustering)

集群消费模式下,相同Consumer Group的每个Consumer实例平均分摊消息。

12 广播消费(Broadcasting)

广播消费模式下,相同Consumer Group的每个Consumer实例都接收全量的消息。

13 普通顺序消息(Normal Ordered Message)

普通顺序消费模式下,消费者通过同一个消息队列( Topic 分区,称作 Message Queue) 收到的消息是有顺序的,不同消息队列收到的消息则可能是无顺序的。

14 严格顺序消息(Strictly Ordered Message)

严格顺序消息模式下,消费者收到的所有消息均是有顺序的。

15 消息(Message)

消息系统所传输信息的物理载体,生产和消费数据的最小单位,每条消息必须属于一个主题。RocketMQ中每个消息拥有唯一的Message ID,且可以携带具有业务标识的Key。系统提供了通过Message ID和Key查询消息的功能。

16 标签(Tag)

为消息设置的标志,用于同一主题下区分不同类型的消息。来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。标签能够有效地保持代码的清晰度和连贯性,并优化RocketMQ提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。

技术架构

rebalance

RocketMQ架构上主要分为四部分,如上图所示:

Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。NameServer:NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活rebalance;路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer和Consumer仍然可以动态感知Broker的路由的信息。

BrokerServer 核心模块

rebalance

Remoting Module:整个Broker的实体,负责处理来自Client端的请求。Client Manager:负责管理客户端(Producer/Consumer)和维护Consumer的Topic订阅信息。Store Service:提供方便简单的API接口处理消息存储到物理硬盘和查询功能。HA Service:高可用服务,提供Master Broker 和 Slave Broker之间的数据同步功能。Index Service:根据特定的Message key对投递到Broker的消息进行索引服务,以提供消息的快速查询。

部署架构

rebalance

RocketMQ 网络部署特点

NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId 来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。 注意:当前RocketMQ版本在部署架构上支持一Master多Slave,但只有BrokerId=1的从服务器才会参与消息的读负载。Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic 服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。Consumer既可以从Master订阅消息,也可以从Slave订阅消息,消费者在向Master拉取消息时,Master服务器会根据拉取偏移量与最大偏移量的距离(判断是否读老消息,产生读I/O),以及从服务器是否可读等因素建议下一次是从Master还是Slave拉取。

结合部署架构图,描述集群工作流程:

启动NameServer,NameServer起来后监听端口,等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。Broker启动,跟所有的NameServer保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有Topic信息。注册成功后,NameServer集群中就有Topic跟Broker的映射关系。收发消息前,先创建Topic,创建Topic时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic。Producer发送消息,启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,轮询从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。

存储架构

rebalance

消息存储架构图中主要有下面三个跟消息存储相关的文件构成。

(1) CommitLog:消息主体以及元数据的存储主体,存储Producer端写入的消息主体内容,消息内容不是定长的。单个文件大小默认1G, 文件名长度为20位,左边补零,剩余为起始偏移量,比如00000000000000000000代表了第一个文件,起始偏移量为0,文件大小为1G=1073741824;当第一个文件写满了,第二个文件为00000000001073741824,起始偏移量为1073741824,以此类推。消息主要是顺序写入日志文件,当文件满了,写入下一个文件;

(2) ConsumeQueue:消息消费队列,引入的目的主要是提高消息消费的性能,由于RocketMQ是基于主题topic的订阅模式,消息消费是针对主题进行的,如果要遍历commitlog文件中根据topic检索消息是非常低效的。Consumer即可根据ConsumeQueue来查找待消费的消息。其中,ConsumeQueue(逻辑消费队列)作为消费消息的索引,保存了指定Topic下的队列消息在CommitLog中的起始物理偏移量offset,消息大小size和消息Tag的HashCode值。consumequeue文件可以看成是基于topic的commitlog索引文件,故consumequeue文件夹的组织方式如下:topic/queue/file三层组织结构,具体存储路径为:$HOME/store/consumequeue/{topic}/{queueId}/{fileName}。同样consumequeue文件采取定长设计,每一个条目共20个字节,分别为8字节的commitlog物理偏移量、4字节的消息长度、8字节tag hashcode,单个文件由30W个条目组成,可以像数组一样随机访问每一个条目,每个ConsumeQueue文件大小约5.72M;

(3) IndexFile:IndexFile(索引文件)提供了一种可以通过key或时间区间来查询消息的方法。Index文件的存储位置是:HOME\store\indexHOME\store\index{fileName},文件名fileName是以创建时的时间戳命名的,固定的单个IndexFile文件大小约为400M,一个IndexFile可以保存 2000W个索引,IndexFile的底层存储设计为在文件系统中实现HashMap结构,故rocketmq的索引文件其底层实现为hash索引。

在上面的RocketMQ的消息存储整体架构图中可以看出,RocketMQ采用的是混合型的存储结构,即为Broker单个实例下所有的队列共用一个日志数据文件(即为CommitLog)来存储。RocketMQ的混合型存储结构(多个Topic的消息实体内容都存储于一个CommitLog中)针对Producer和Consumer分别采用了数据和索引部分相分离的存储结构,Producer发送消息至Broker端,然后Broker端使用同步或者异步的方式对消息刷盘持久化,保存至CommitLog中。只要消息被刷盘持久化至磁盘文件CommitLog中,那么Producer发送的消息就不会丢失。正因为如此,Consumer也就肯定有机会去消费这条消息。当无法拉取到消息后,可以等下一次消息拉取,同时服务端也支持长轮询模式,如果一个消息拉取请求未拉取到消息,Broker允许等待30s的时间,只要这段时间内有新消息到达,将直接返回给消费端。这里,RocketMQ的具体做法是,使用Broker端的后台服务线程—ReputMessageService不停地分发请求并异步构建ConsumeQueue(逻辑消费队列)和IndexFile(索引文件)数据。

消息刷盘

rebalance

同步刷盘:只有在消息真正持久化至磁盘后RocketMQ的Broker端才会真正返回给Producer端一个成功的ACK响应。同步刷盘对MQ消息可靠性来说是一种不错的保障,但是性能上会有较大影响,一般适用于金融业务应用该模式较多。

rebalance

异步刷盘:能够充分利用OS的PageCache的优势,只要消息写入PageCache即可将成功的ACK返回给Producer端。消息刷盘采用后台异步线程提交的方式进行,降低了读写延迟,提高了MQ的性能和吞吐量

其它设计原理

通信机制:协议设计、IO模型(Reactor)消息过滤:Tag、SQL负载均衡:Product(自增取模)、Consumer(平均分配)事务/延迟消息:替换Topic死信队列:消费16次失败消息查询:IndexFile索引文件Rebalance:队列与Consumer重新建立关系消息样例

普通消息-同步发送

rebalance

此种方式应用场景非常广泛,例如重要通知邮件、报名短信通知、营销短信系统等。

普通消息-异步发送

rebalance

异步发送一般用于链路耗时较长,对响应时间较为敏感的业务场景,例如,您视频上传后通知启动转码服务,转码完成后通知推送转码结果等。

普通消息-单向发送

rebalance

适用于某些耗时非常短,但对可靠性要求并不高的场景,例如日志收集。

普通消息-三种发放方式对比

rebalance

顺序消息

在MQ的模型中,顺序需要由3个阶段去保障:

消息发送时保持顺序消息被存储时保持和发送的顺序⼀致消息被消费时保持和存储的顺序⼀致rebalance

rebalance

上图是RocketMQ顺序消息原理的介绍,将不同订单的消息路由到不同的分区中。文档只是给出了Producer顺序的处理,Consumer消费时通过一个分区只能有一个线程消费的方式来保证消息顺序。

顺序消息-Producer

rebalance

顺序消息-Consumer

rebalance

总结:从上面顺序消息的发送和接收代码可以看出,在发送时是采用取模方式进行选择固定队列 ,在接收时是采用单线程的方式去消费队列,从而保证消息的顺序性。(注:单核单线程情况)

延迟消息

延迟消息处理流程:

修改消息Topic名称和队列信息转发消息到延迟主题SCHEDULE_TOPIC_XXXX的CosumeQueue中延迟服务消费SCHEDULE_TOPIC_XXXX消息将信息重新存储到CommitLog中将消息投递到⽬标Topic中消费者消费⽬标topic中的数据rebalance

ConsumerQueue格式说明

rebalance

Commit Log Offset:记录在CommitLog中的位置。

Size:记录消息的大小

Message Tag HashCode:记录消息Tag的哈希值,用于消息过滤。特别的,对于延迟消息,这个字段记录的是消息的投递时间戳。这也是为什么java中hashCode方法返回一个int型,只占用4个字节,而这里Message Tag HashCode字段却设计成8个字节的原因

广播消息

rebalance

批量消息

rebalance

批量发送可以提⾼发送性能,但有⼀定的限制:

topic相同不⽀持延时发送⼀批消息的⼤⼩不能⼤于 4M(分词器解决: ListSplitter )

事务消息

rebalance

事务消息发送:

1. 发送⽅将半事务消息发送⾄消息队列 RocketMQ 版服务端。

2. 消息队列 RocketMQ 版服务端将消息持久化成功之后,向发送⽅返回 Ack 确认消息已经发送成功,此时消息为半事务消息。

3. 发送⽅开始执⾏本地事务逻辑。

4. 发送⽅根据本地事务执⾏结果向服务端提交⼆次确认(Commit 或是 Rollback),服务端收到 Commit 状态则将半事务消息标记为可投递,订阅⽅最终将收到该消息;服务端收到 Rollback 状态则删除半事务消息,订阅⽅将不会接受该消息。

事务消息回查:

1.在断⽹或者是应⽤重启的特殊情况下,上述步骤 4 提交的⼆次确认最终未到达服务端,经过固定 时间后服务端将对该消息发起消息回查。

2. 发送⽅收到消息回查后,需要检查对应消息的本地事务执⾏的最终结果。

3. 发送⽅根据检查得到的本地事务的最终状态再次提交⼆次确认,服务端仍按照步骤 4 对半事务消 息进⾏操作。

事务状态

事务消息共有三种状态,提交状态、回滚状态、中间状态:

TransactionStatus.CommitTransaction: 提交事务,它允许消费者消费此消息。TransactionStatus.RollbackTransaction: 回滚事务,它代表该消息将被删除,不允许被消费。TransactionStatus.Unknown: 中间状态,它代表需要检查消息队列来确定状态。

事务消息-Producer

rebalance

事务消息-Listener

rebalance

事务消息原理

rebalance

HALF消息:

RMQ_SYS_TRANS_HALF_TOPIC(临时存放消息信息)事务消息替换主题,保存原主题和队列信息半消息对Consumer不可⻅,不会被投递

OP消息:

RMQ_SYS_TRANS_OP_HALF_TOPIC(记录⼆阶段操作)Rollback:只做记录Commit:根据备份信息重新构造消息并投递

回查: 对⽐HALF消息和OP消息进⾏回查

结语

Rocket MQ是目前MQ产品中使用非常广泛的,它既可以保证数据的传输可靠性,又有很可观的性能表现,这也是它越来越受欢迎的原因。

本文 麒麟点评 原创,转载保留链接!网址:http://kylinpackage.com.cn/dianping/15092.html

标签:rebalance
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
关注我们

扫一扫关注我们,了解最新精彩内容