RocketMQ架构解析


注:本文为RocketMQ系列文章第一讲。

前言

从本篇文章开始, 笔者将持续推出rocketmq系列博客。博客内容围绕对RocketMQ源码研究展开。 同时, 笔者也会结合实际运维过程中遇到的一系列问题, 从架构和源码层面给出解答。系列博客所探讨内容基于rocketmq开源版本4.6.0展开。
注: 笔者之所以写RocketMQ系列博客有两个原因, 其一, 希望能对RocketMQ细节感兴趣或在工作中遇到问题的人有所帮助; 其二, 是希望将工作中的所学所做所想沉淀下来

总体架构

请添加图片描述
上图摘自官网 , 是rocketmq经典的架构描述。整个集群可概括为两大组成部分, 即服务端和客户端。客户端由生产者集群和消费者集群组成; 服务端则由NameServer集群和Broker集群构成。每个部分核心功能概括如下:

  • Producer
    消息生产者的角色,通过RocketMQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。

  • Consumer
    消息消费的角色,支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。

  • NameServer
    NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:(1) Broker管理: NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活;(2) 路由信息管理: 每个NameServer保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。
    NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer, Consumer仍然可以动态感知Broker的路由的信息。

  • BrokerServer
    Broker主要负责消息的存储、投递和查询以及服务高可用保证。

消息存储概述

RocketMQ所有消息均存储在Broker上, Broker支持分布式部署, 具有动态扩所容、集群容错等特点。RocketMQ所有消息(元信息除外)统一 以二进制的形式追加在commitlog文件中, 每个commitlog文件默认大小为1G(可配置), 并以存储最小偏移量命名, 一个commitlog文件存满, 会重新打开另一个存储。
请添加图片描述

RocketMQ消息存储结构如上图。从存储结构来看, RocketMQ在物理存储之上进行了两层抽象, 即主题和队列。

  • 主题(Topic)
    主题是消息存储的第一层抽象, 主题从上层实现了消息隔离, 常常和业务相关。在使用上, 一般会根据不同的业务属性和业务含义申请不同的主题。
  • 队列(queue)
    第二层抽象是“队列”(queue), 队列在rocketmq中是一个逻辑概念, 它并不存储实际的消息, 存储的是消息在commitlog中的物理偏移量(可简单理解为消息的索引)。一个主题可以包含多个队列, 主题队列可分布在不同的broker上。队列的引入是rocketmq动态扩容思想的点睛之笔, 它是客户端负载均衡分配的最小单位, 同时也是顺序消息、定时消息实现的基础。

消息发送概述

请添加图片描述
消息发送以主题为单位, 即发送消息时需要指定对应的topic。上图简单示意了消息发送逻辑。发送过程总结如下:

  • 生产者
    首先生产者获取主题的元信息(主题的队列); 然后通过负载均衡选择发送的队列queue, 并从元信息中查找队列所在的broker地址; 最后, 将消息内容, 队列信息统一发送给broker。
  • Broker
    Broker接收到消息后, 首先将消息追加到commitlog文件中(消息分发到具体队列由分发线程完成), 追加成功后应答客户端。至此, 一次发送任务完成。

客户端是如何知道主题队列信息的呢?
首先Broker启动时, 会开启定时任务, 定时将Broker上所有队列元信息注册到所有NameServer。NameServer以主题为单位, 将所有Broker上的队列元信息汇总, 维护在路由表中。客户端发送消息前, 首先从NameServer路由表获取队列元信息, 然后再执行发送逻辑。

消息消费概述

RocketMQ消息消费有两种模式, 推模式和拉模式。用户常选择推模式消费, 即一旦有消息到达Broker就推送给消费者消费。RocketMQ内部并没有真正实现推模式, 所谓的推模式实际上是一种“循环拉模式”, 核心过程我们后面有专门章节详细分析。
请添加图片描述
上图展示了rocketmq消息消费示意图, 和消息发送一样, 消息消费也是以主题为单位, 关于主题路由信息拉取, 已在消息发送概述中阐明, 此处不再累述。以集群模式消费为例, 消息消费由三个核心线程完成, 核心过程如下:
(1) 消费者启动时, 首先获取主题的路由信息, 然后向所有包含消费主题的Broker 上报心跳信息;
(2) 负载均衡线程, 从NameServer获取主题所有队列信息mqAll, 并从broker端获取所有消费客户端cidAll, 然后根据负载均衡算法计算当前客户端分配到的队列信息(上图采用均匀分发策略), 并将分配信息处理组装交付消息拉取线程处理;
(3) 消息拉取线程根据队列分配信息, 轮训(默认长轮训)从broker端对应的队列上拉取消息到本地, 组装后交付消费线程处理;
(4) 消息消费线程消费消息拉取线程分发的消费任务, 消费消息并处理消费结果。至此一次消费任务完成。
注: 使用时配置的消费线程数, 实际上就是消息消费线程数.

总结

RocketMQ架构解析内容到这里就结束了, 本次内容只是从宏观上对RocketMQ各组成部分进行讲解, 并未过多涉及细节。每部分的运作细节我们会在后续系列文档中结合源码逐一剖析, 欢迎继续关注。
如果读者有任何问题或想要了解的细节, 可以在文章后留言, 笔者会尽所能, 对问题进行认真解答。
注: 因笔者技术水平有限, 文章中描述不准确的地方, 还请多多批评指正。

参考内容: RocketMQ官方文档

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值