前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Apache RocketMQ 基础概念及架构解析

Apache RocketMQ 基础概念及架构解析

作者头像
zoro
发布2019-04-11 15:35:10
7050
发布2019-04-11 15:35:10
举报
文章被收录于专栏:Java开发者Java开发者Java开发者

Apache RocketMQ 基础概念及架构解析
Apache RocketMQ 系列:

Apache RocketMQ之JMS基本概念及使用:https://cloud.tencent.com/developer/article/1412675

Apache RocketMQ 基础概念及架构解析:https://cloud.tencent.com/developer/article/1412649

Apache RocketMQ 的基础特性介绍:https://cloud.tencent.com/developer/article/1412645

Apache RocketMQ 集群搭建(两主两从):https://cloud.tencent.com/developer/article/1412653

Apache RocketMQ 刷盘策略与复制策略: https://cloud.tencent.com/developer/article/1412663

优秀博客:

https://blog.csdn.net/BtB5e6Nsu1g511Eg5XEg/article/details/83828893

https://blog.csdn.net/GV7lZB0y87u7C/article/details/78382605

https://blog.csdn.net/qq_34021712/article/details/78169014

https://blog.csdn.net/babyupup/article/details/72642571

https://www.jianshu.com/p/f90b0f175e2d


本文主要介绍:

一、RocketMQ起源

二、RocketMQ的概念模型

三、RocketMQ的存储模型

四、RocketMQ的部署模型

五、RocketMQ最佳实践总结 (后面介绍)


一、RocketMQ的起源

通常,每个产品的诞生都源于一个具体的需求或问题,RocketMQ也不例外。起初,产品的原型像一个巨石,把所有需要实现的程序和接口都罗列到一起。但随着公司业务的发展,所有的系统和功能都在这个巨石上开发,当覆盖几百上千名开发人员的时候,瓶颈就出来了。这时候,就需要我们把系统进行分解。

1.png

分解后,就出现了上图中的分布式架构,这类架构最大的特点就是解耦,而RocketMQ的异步解耦意味着底层的重构不会影响到上层应用的功能。RocketMQ另一个优势是削峰填谷,在面临流量的不确定性时,实现对流量的缓冲处理。此外,RocketMQ的顺序设计特性使得RocketMQ成为一个天然的排队引擎,例如,三个应用同时对一个后台引擎发起请求,排队引擎的特性可以确保不会引起“撞车”事故。

总结:RocketMQ的作用(消息中间件):解耦、削峰填谷、高并发,或者说:异步消息处理、高性能(高并发读写)、高可用(主备)、可伸缩(削峰填谷)、最终一致性。

补充:

在2007年的时候,淘宝实施了“五彩石”项目,“五彩石”用于将交易系统从单机变成分布式,也是在这个过程中产生了阿里巴巴第一代消息引擎——Notify。 在2010年的时候,阿里巴巴B2B部门基于ActiveMQ的5.1版本也开发了自己的一款消息引擎,称为Napoli,这款消息引擎在B2B里面广泛地被使用,不仅仅是在交易领域,在很多的后台异步解耦等方面也得到了广泛的应用。 在2011年的时候,业界出现了现在被很多大数据领域所推崇的Kafka消息引擎,阿里巴巴在研究了Kafka的整体机制和架构设计之后,基于Kafka的设计使用Java进行了完全重写并推出了MetaQ 1.0版本,主要是用于解决顺序消息和海量堆积的问题。 在2012年,阿里巴巴对于MetaQ进行了架构重组升级,开发出了MetaQ 2.0,这时就发现MetaQ原本基于Kafka的架构在阿里巴巴如此庞大的体系下很难进行水平扩展,所以在2012年的时候就开发了RocketMQ 3.0版本。很多人会问到RocketMQ 3.0和MetaQ 3.0的区别,其实这两者是等价的版本,只不过阿里内部使用的称为MetaQ 3.0,外部开源称之为RocketMQ 3.0。 在2015年,又基于RocketMQ开发了阿里云上的Aliware MQ和Notify 3.0。 在2016年的时候,阿里巴巴将RocketMQ的内核引擎捐赠给了Apache基金会。 以上就是RocketMQ的整体发展历史,其实在阿里巴巴内部围绕着RocketMQ内核打造了三款产品,分别是MetaQ、Notify和Aliware MQ。这三者分别采用了不同的模型,MetaQ主要使用了拉模型,解决了顺序消息和海量堆积问题;Notify主要使用了推模型,解决了事务消息;而云产品Aliware MQ则是提供了商业化的版本。


二、RocketMQ的概念模型

对于任何一款中间件产品而言,清晰的概念模型是帮助开发者正确理解使用它的关键。从RocketMQ的概念模型来看:Topic是用于存储逻辑的地址的,Producer是信息的发送,Consumer是信息的接收者。

2.png

这只是一个基础的概念模型,在实际的生产中,结构会更复杂,例如我们需要对中间的Topic进行分区,出现多个有关联的Topic,再如同一个信息的发送方会有多个订阅者,同一个需求方会有多个发送方,出现一对多、多对一的情况。

3.png

上图就是对Topic、Producer、Consumer扩展后的概念模型。RocketMQ中可以接触到的所有概念都可以在这个概念模型图中找到。

左边有两个Producer,中间就是两个分布式的Topic,用于存储逻辑地址的两个Topic中分别有两个用于存储物理存储地址的Message Queue,Broker是实际部署过程的对应的一台设备,右边则是两个Consumer,Consumer Group是代表两个Consumer可共享相互之间的订阅。不同的Consumer Group相互独立。

一句话总结就是不同的Group是广播订阅的,同一个Group则是负载订阅的。图中的连线表示各模块之间的关系,例如Consumer Group A中的Consumer1对应着Message Queue0和Message Queue1的两个队列,分布在BrokerA这一台设备上。

补充:

Producer Group: 用来表示一个収送消息应用,一个 Producer Group 下包含多个 Producer 实例,可以是多台机器,也可以 是一台机器的多个迕程,戒者一个迕程的多个 Producer 对象。一个 Producer Group 可以収送多个 Topic 消息,Producer Group 作用如下:

  1. 标识一类 Producer
  2. 可以通过运维工具查询返个収送消息应用下有多个 Producer 实例
  3. 収送分布式事务消息时,如果 Producer 中途意外宕机,Broker 会主劢回调 Producer Group 内的任意一台机器来确讣事务状态

Consumer Group: 用来表示一个消费消息应用,一个 Consumer Group 下包含多个 Consumer 实例,可以是多台机器,也可 以是多个迕程,戒者是一个迕程的多个 Consumer 对象。一个 Consumer Group 下的多个 Consumer 以均摊 方式消费消息,如果设置为广播方式,那举返个 Consumer Group 下的每个实例都消费全量数据。 Topoic:消息的逻辑管理单位。 Message Queue:消息的物理管理单位。一个Topic下可以有多个Queue,Queue的引入使得消息存储可以分布式集群化,具有了水平扩展的能力。 顺序消息:用户实现MessageQueueSelector为某一批消息(通常是有同样的唯一的标示ID),选择同一个Queue,则这一批消息的消费将是顺序消费(并由同一个consumer完成消费)。 事务消息:这样的消息有多个状态,并且其发送是两阶段的。第一个阶段发送PREPARED状态的消息,此时consumer是看不见这种状态的消息的,发送完毕后回调用户的TransactionExecutor接口,执行相应的事务操作(如数据库),当事务操作成功时,则对此条消息返回commit,让broker对该消息执行commit操作,成为commit状态的消息对consumer是可见的。


三、RocketMQ的存储模

RocketMQ的消息的存储是由ConsumeQueue和CommitLog 配合来完成的,ConsumeQueue中只存储很少的数据,消息主体都是通过CommitLog来进行读写。

4.png

CommitLog:

是消息主体以及元数据的存储主体,对CommitLog建立一个ConsumeQueue,每个ConsumeQueue对应一个(概念模型中的)MessageQueue,所以只要有Commit Log在,Consume Queue即使数据丢失,仍然可以恢复出来。

Consume Queue:

是一个消息的逻辑队列,存储了这个Queue在CommitLog中的起始offset,log大小和MessageTag的hashCode。每个Topic下的每个Queue都有一个对应的ConsumerQueue文件,例如Topic中有三个队列,每个队列中的消息索引都会有一个编号,编号从0开始,往上递增。并由此一个位点offset的概念,有了这个概念,就可以对Consumer端的消费情况进行队列定义。

补充:

RocketMQ的broker端,不负责推送消息,无论消费者是否消费消息,都将消息存储起来。谁要消费消息,就向broker发请求获取消息,消费记录由consumer来维护。RocketMQ提供了两种存储方式来保留消费记录:一种是保留在consumer所在的服务器上;另一种是保存在broker服务器上。用户还可以自己实现相应的消费进度存储接口。 默认情况下,采用集群消费(CLUSTERING),会将记录保存在broker端;而采用广播消费(BROADCASTING)则会将消费记录保存在本地。 RocketMQ以Topic来管理不同应用的消息。对于生产者而言,发送消息是,需要指定消息的Topic,对于消费者而言,在启动后,需要订阅相应的Topic,然后可以消费相应的消息。Topic是逻辑上的概念,在物理实现上,一个Topic由多个Queue组成,采用多个Queue的好处是可以将Broker存储分布式化,提高系统性能。 RocketMQ中,producer将消息发送给Broker时,需要制定发送到哪一个队列中,默认情况下,producer会轮询的将消息发送到每个队列中(所有broker下的Queue合并成一个List去轮询)。 对于consumer而言,会为每个consumer分配固定的队列(如果队列总数没有发生变化),consumer从固定的队列中去拉取没有消费的消息进行处理。

RocketMQ 存储特点:

零拷贝原理:Consumer 消费消息过程,使用了零拷贝,零拷贝包含以下两种方式:

  1. 使用 mmap + write 方式

优点:即使频繁调用,使用小块文件传输,效率也很高 缺点:不能很好的利用 DMA 方式,会比 sendfile 多消耗CPU,内存安全性控制复杂,需要避免 JVM Crash 问题。

  1. 使用 sendfile 方式

优点:可以利用 DMA 方式,消耗 CPU 较少,大块文件传输效率高,无内存安全新问题。 缺点:小块文件效率低亍 mmap 方式,只能是 BIO 方式传输,不能使用 NIO。 RocketMQ 选择了第一种方式,mmap+write 方式,因为有小块数据传输的需求,效果会比 sendfile 更好。

RocketMQ 文件系统:

RocketMQ 选择 Linux Ext4 文件系统。 原因如下: Ext4 文件系统删除 1G 大小的文件通常耗时小亍 50ms,而 Ext3 文件系统耗时约 1s 左右,且删除文件时,磁盘 IO 压力极大,会导致 IO 写入超时。 文件系统局面需要做以下调优措施: 文件系统 IO 调度算法需要调整为 deadline,因为 deadline 算法在随机读情况下,可以合幵读请求为顺序跳跃 方式,从而提高读 IO 吞吐量。

RocketMQ 数据存储结构:

5.png

RocketMQ 存储目录结构
|-- abort 
|-- checkpoint 
|-- config
| |-- consumerOffset.json
| |-- consumerOffset.json.bak
| |-- delayOffset.json
| |-- delayOffset.json.bak
| |-- subscriptionGroup.json.bak
| |-- topics.json
| |-- topics.json.bak 
|-- commitlog
| |-- 00000003384434229248
| |-- 000000033855079710
| |-- 0000000338658171289
|-- consumequeue
  |-- %DLQ%ConsumerGroupA
  | |-- 0
  | | |-- 00000000000006000000
  |-- %RETRY%ConsumerGroupA
  | |-- 0
  | | |-- 00000000000000000000
  |-- %RETRY%ConsumerGroupB
  | |-- 0
  | | |-- 00000000000000000000
  |-- SCHEDULE_TOPIC_XXXX
  | |-- 2
  | | |-- 00000000000006000000
  | |-- 3
  | | |-- 00000000000006000000
  |-- TopicA
  | |-- 0
  | | |-- 00000000002604000000
  | | |-- 00000000002610000000
  | | |-- 00000000002616000000
  | |-- 1
  | | |-- 00000000002610000000
  | | |-- 00000000002610000000
  |-- TopicB
  | |-- 0
  | | |-- 00000000000732000000
  | |-- 1
  | | |-- 00000000000732000000
  | |-- 2
  | | |-- 00000000000732000000

四、RocketMQ的部署模型

在实际的部署过程中,Broker是实际存储消息的数据节点,Nameserver则是服务发现节点,Producer发送消息到某一个Topic,并给到某个Consumer用于消费的过程中,需要先请求Nameserver拿到这个Topic的路由信息,即Topic在哪些Broker上有,每个Broker上有哪些队列,拿到这些请求后再把消息发送到Broker中;相对的,Consumer在消费的时候,也会经历这个流程。

6.png

补充:

NameServer:

NameServer是一个几乎无状态节点,可集群部署,节点之间无任何信息同步(类似ZK)。 NameServer用于存储Topic、Broker关系信息,功能简单,稳定性高。多个NameServer之间相互没有通信,单台NameServer宕机不影响其他NameServer与集群;即使整个NameServer集群宕机,已经正常工作的Producer,Consumer,Broker仍然能正常工作,但新起的Producer, Consumer,Broker就无法工作。 NameServer压力不会太大,平时主要开销是在维持心跳和提供Topic-Broker的关系数据。但有一点需要注意,Broker向NameServer发心跳时,会带上当前自己所负责的所有Topic信息,如果Topic个数太多(万级别),会导致一次心跳中,就Topic的数据就几十M,网络情况差的话,网络传输失败,心跳失败,导致NameServer误认为Broker心跳失败。

Broker :

Broker 部署相对复杂,Broker分为Master 与 Slave,一个Master可以对应多个 Slave,但是一个Slave只能对应一个Master。 Master 与 Slave 的对应关系通过指定相同的BrokerName,不同的 BrokerId 来定义,BrokerId为0表示Master,非 0 表示 Slave。 Master可以部署多个。每个Broker与NameServer 集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。 Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从 Name Server 取 Topic 路由信息,并向提供 Topic 服务的 Master 建立长连接,且定时向 Master 发送心跳。

Producer :

Producer 完全无状态,可集群部署。 Producer启动时,也需要指定NameServer的地址,从NameServer集群中选一台建立长连接。如果该NameServer宕机,会自动连其他NameServer。直到有可用的NameServer为止。 Producer每30秒从NameServer获取Topic跟Broker的映射关系,更新到本地内存中。再跟Topic涉及的所有Broker建立长连接,每隔30秒发一次心跳。在Broker端也会每10秒扫描一次当前注册的Producer,如果发现某个Producer超过2分钟都没有发心跳,则断开连接。 Producer发送时,会自动轮询当前所有可发送的broker,一条消息发送成功,下次换另外一个broker发送,以达到消息平均落到所有的broker上。 假如某个Broker宕机,意味生产者最长需要30秒才能感知到。在这期间会向宕机的Broker发送消息。当一条消息发送到某个Broker失败后,会往该broker自动再重发2次,假如还是发送失败,则抛出发送失败异常。业务捕获异常,重新发送即可。客户端里会自动轮询另外一个Broker重新发送,这个对于用户是透明的。

Consumer:

Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向 Master、Slave发送心跳。 Consumer既可以从Master订阅消息,也可以从 Slave 订阅消息,订阅规则由 Broker 配置决定。 Consumer启动时需要指定NameServer地址,与其中一个NameServer建立长连接。消费者每隔30秒从NameServer获取所有Topic的最新队列情况,这意味着某个Broker如果宕机,客户端最多要30秒才能感知。连接建立后,从NameServer中获取当前消费Topic所涉及的Broker,直连Broker。 Consumer跟Broker是长连接,会每隔30秒发心跳信息到Broker。Broker端每10秒检查一次当前存活的Consumer,若发现某个Consumer 2分钟内没有心跳,就断开与该Consumer的连接,并且向该消费组的其他实例发送通知,触发该Consumer集群的负载均衡。 Consumer有两种模式消费:集群消费,广播消费。 广播消费:每个消费者消费Topic下的所有队列。 集群消费:一个topic可以由同一个ID下所有消费者分担消费。


五、RocketMQ最佳实践总结

Apache RocketMQ 集群搭建(两主两从):https://cloud.tencent.com/developer/article/1412653


如有问题,请留言:)。
如需转载,请注明出处:)。
感觉有帮助,可以点下喜欢:)。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.12.25 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Apache RocketMQ 基础概念及架构解析
    • Apache RocketMQ 系列:
      • 本文主要介绍:
        • 一、RocketMQ的起源
          • 二、RocketMQ的概念模型
            • 三、RocketMQ的存储模
              • CommitLog:
                • Consume Queue:
                  • RocketMQ 存储特点:
                  • RocketMQ 文件系统:
                • RocketMQ 数据存储结构:
                  • RocketMQ 存储目录结构
                  • 四、RocketMQ的部署模型
                  • NameServer:
                  • Broker :
                  • Producer :
                  • Consumer:
                  • 五、RocketMQ最佳实践总结
                  • 如有问题,请留言:)。
                  • 如需转载,请注明出处:)。
                  • 感觉有帮助,可以点下喜欢:)。
              相关产品与服务
              对象存储
              对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档