Rocketmq源码分析(一)整体架构

1 系列

  • 整体架构图
  • producer端发送消息
  • broker端接收消息
  • broker端消息的存储
  • consumer消费消息
  • 分布式事务的实现
  • 定时消息的实现
  • 关于顺序消费
  • 关于重复消息
  • 关于高可用

2 整体架构图

先来看下官方给出的整体架构图

  • Producer集群:拥有相同的producerGroup,一般来讲,Producer不必要有集群的概念,这里的集群仅仅在RocketMQ的分布式事务中有用到
  • Name Server集群:提供topic的路由信息,路由信息数据存储在内存中,broker会定时的发送路由信息到nameserver中的每一个机器,来进行更新,所以name server集群可以简单理解为无状态(实际情况下可能存在每个nameserver机器上的数据有短暂的不一致现象,但是通过定时更新,大部分情况下都是一致的)
  • broker集群:一个集群有一个统一的名字,即brokerClusterName,默认是DefaultCluster。一个集群下有多个master,每个master下有多个slave。master和slave算是一组,拥有相同的brokerName,不同的brokerId,master的brokerId是0,而slave则是大于0的值。master和slave之间可以进行同步复制或者是异步复制。
  • consumer集群:拥有相同的consumerGroup。

下面来说说他们之间的通信关系

  • Producer和Name Server:每一个Producer会与Name Server集群中的一台机器建立TCP连接,会从这台Name Server上拉取路由信息。
  • Producer和broker:Producer会和它要发送的topic相关的master类型的broker建立TCP连接,用于发送消息以及定时的心跳信息。broker中会记录该Producer的信息,供查询使用
  • broker与Name Server:broker(不管是master还是slave)会和每一台Name Server机器来建立TCP连接。broker在启动的时候会注册自己配置的topic信息到Name Server集群的每一台机器中。即每一台Name Server都有该broker的topic的配置信息。master与master之间无连接,master与slave之间有连接
  • Consumer和Name Server:每一个Consumer会和Name Server集群中的一台机器建立TCP连接,会从这台Name Server上拉取路由信息,进行负载均衡
  • Consumer和broker:Consumer可以与master或者slave的broker建立TCP连接来进行消费消息,Consumer也会向它所消费的broker发送心跳信息,供broker记录。

3 kafka的架构图

来看下kafka的整体架构图

来看看他们之间的连接关系

  • Producer和broker:Producer会和它所要发送的topic相关的broker建立TCP连接,并通过broker进行其他broker的发现(这个没有依赖ZooKeeper进行服务发现)
  • broker和ZooKeeper:broker会将自己注册在ZooKeeper上,同时依赖ZooKeeper做一些分布式协调
  • Consumer和ZooKeeper:Consumer会将自己注册在ZooKeeper上,同时依赖ZooKeeper进行broker发现以及将消费offset记录在ZooKeeper上
  • Consumer和Broker:Consumer连接topic相关的broker进行消息的消费

4 RocketMQ和kafka的对比

4.1 消息的存储

我们知道topic是一类消息的统称,为了提高消息的写入和读取并发能力,将一个topic的消息进行拆分,可以分散到多个broker中。kafka上称为分区,而RocketMQ称为队列。

对于kafka:为了防止一个分区的消息文件过大,会拆分成一个个固定大小的文件,所以一个分区就对应了一个目录。分区与分区之间是相互隔离的。

对于RocketMQ:则是所有topic的数据混在一起进行存储,默认超过1G的话,则重新创建一个新的文件。消息的写入过程即写入该混杂的文件中,然后又有一个线程服务,在不断的读取分析该混杂文件,将消息进行分拣,然后存储在对应队列目录中(存储的是简要信息,如消息在混杂文件中的offset,消息大小等)

所以RocketMQ需要2次寻找,第一次先找队列中的消息概要信息,拿到概要信息中的offset,根据这个offset再到混杂文件中找到想要的消息。而kafka则只需要直接读取分区中的文件即可得到想要的消息。

看下这里给出的RocketMQ的日志文件图片分布式开放消息系统(RocketMQ)的原理与实践

这里我自己认为RocketMQ的做法还是值得商榷的,这样的做法在同步刷盘、异步刷盘时效率相对高些(由于量大所以效率相对高些),但是全部的topic往一个文件里面写,每次写入要进行加锁控制,本来不相干的topic却相互影响,就降低的写入的效率。这个锁的粒度有点大了,我自己认为应该一个队列对应一个CommitLog,这样做就是减少锁的粒度问题。

4.1 Prdocuer端的服务发现

就是Producer端如何来发现新的broker地址。

对于kafka来说:Producer端需要配置broker的列表地址,Producer也从一个broker中来更新broker列表地址(从中发现新加入的broker)。

对于RocketMQ来说:Producer端需要Name Server的列表地址,同时还可以定时从一个HTTP地址中来获取最新的Name Server的列表地址,然后从其中的一台Name Server来获取全部的路由信息,从中发现新的broker。

4.1 消费offset的存储

对于kafka:Consumer将消费的offset定时存储到ZooKeeper上,利用ZooKeeper保障了offset的高可用问题。

对于RocketMQ:Consumer将消费的offset定时存储到broker所在的机器上,这个broker优先是master,如果master挂了的话,则会选择slave来存储,broker也是将这些offset定时刷新到本地磁盘上,同时slave会定时的访问master来获取这些offset。

4.2 consumer负载均衡

对于负载均衡,在出现分区或者队列增加或者减少的时候、Consumer增加或者减少的时候都会进行reblance操作。

对于RocketMQ:客户端自己会定时对所有的topic的进行reblance操作,对于每个topic,会从broker获取所有Consumer列表,从broker获取队列列表,按照负载均衡策略,计算各自负责哪些队列。这种就要求进行负载均衡的时候,各个Consumer获取的数据是一致的,不然不同的Consumer的reblance结果就不同。

对于kafka:kafka之前也是客户端自己进行reblance,依靠ZooKeeper的监听,来监听上述2种情况的出现,一旦出现则进行reblance。现在的版本则将这个reblance操作转移到了broker端来做,不但解决了RocketMQ上述的问题,同时减轻了客户端的操作,是的客户端更加轻量级,减少了和其他语言集成的工作量。详细见这篇文章Kafka设计解析(四):Kafka Consumer解析

4.3 Name Server和ZooKeeper

Name Server和ZooKeeper的作用大致是相同的,从宏观上来看,Name Server做的东西很少,就是保存一些运行数据,Name Server之间不互连,这就需要broker端连接所有的Name Server,运行数据的改动要发送到每一个Name Server来保证运行数据的一致性(这个一致性确实有点弱),这样就变成了Name Server很轻量级,但是broker端就要做更多的东西了。

而ZooKeeper呢,broker只需要连接其中的一台机器,运行数据分发、一致性都交给了ZooKeeper来完成。

目前先就这几个大的组件进行简单的对比,后续会对某些细节进行详细说明。

时间: 2024-11-03 12:54:07

Rocketmq源码分析(一)整体架构的相关文章

jQuery源码分析-01总体架构分析_jquery

1. 总体架构 1.1 自调用匿名函数 self-invoking anonymous function 打开jQuery源码,首先你会看到这样的代码结构: 复制代码 代码如下: (function( window, undefined ) { // jquery code })(window); 1. 这是一个自调用匿名函数.什么东东呢?在第一个括号内,创建一个匿名函数:第二个括号,立即执行 2. 为什么要创建这样一个"自调用匿名函数"呢? 通过定义一个匿名函数,创建了一个"

OkHttp 3.7源码分析(一)——整体架构

OkHttp3.7源码分析文章列表如下: OkHttp源码分析--整体架构 OkHttp源码分析--拦截器 OkHttp源码分析--任务队列 OkHttp源码分析--缓存策略 OkHttp源码分析--多路复用 OkHttp是一个处理网络请求的开源项目,是Android端最火热的轻量级框架,由移动支付Square公司贡献用于替代HttpUrlConnection和Apache HttpClient.随着OkHttp的不断成熟,越来越多的Android开发者使用OkHttp作为网络框架. 之所以可以

vue2.0源码分析之理解响应式架构

分享前啰嗦 我之前介绍过vue1.0如何实现observer和watcher.本想继续写下去,可是vue2.0横空出世..所以 直接看vue2.0吧.这篇文章在公司分享过,终于写出来了.我们采用用最精简的代码,还原vue2.0响应式架构实现 以前写的那篇 vue 源码分析之如何实现 observer 和 watcher可以作为本次分享的参考. 不过不看也没关系,但是最好了解下Object.defineProperty 本文分享什么 理解vue2.0的响应式架构,就是下面这张图 顺带介绍他比rea

HDFS源码分析DataXceiver之整体流程

        在<HDFS源码分析之DataXceiverServer>一文中,我们了解到在DataNode中,有一个后台工作的线程DataXceiverServer.它被用于接收来自客户端或其他数据节点的数据读写请求,为每个数据读写请求创建一个单独的线程去处理.而处理每次读写请求时所创建的线程,就是本文要讲的DataXceiver.本文,我们来看下DataXceiver的具体实现,着重讲解下它得到数据读写请求后的整体处理流程.         首先,我们先看下DataXceiver的成员变

springboot源码分析3-springboot之banner类架构以及原理

继续上文的<<springboot源码分析2-springboot 之banner定制以及原理章节>>进行讲解,上一节我们详细详解了banner的三种输出模式.banner的输出模式设置.banner类的架构.SpringApplicationBannerPrinter类.ImageBanner以及TextBanner的处理方式.本小节我们来重点讲解一下各种banner处理类的相关实现逻辑以及设计意图和职责. 1.1 SpringBootBanner类 SpringBootBann

JUnir源码分析(一)

一.引子 JUnit源码是我仔细阅读过的第一个开源项目源码.阅读高手写的代码能学到一些好的编程风格和实现思路,这是提高自己编程水平行之有效的方法,因此早就想看看这些赫赫有名的框架是怎么回事了.今天就拿最简单的JUnit下手,也算开始自己的源码分析之路.   JUnit作为最著名的单元测试框架,由两位业界有名人士协力完成,已经经历了多次版本升级(了解JUnit基础.JUnit实践).JUnit总体来说短小而精悍,有不少值得我们借鉴的经验在里面:但是也有一些不足存在,当然这对于任何程序来说都是难免的

深入理解Spark:核心思想与源码分析

大数据技术丛书 深入理解Spark:核心思想与源码分析 耿嘉安 著 图书在版编目(CIP)数据 深入理解Spark:核心思想与源码分析/耿嘉安著. -北京:机械工业出版社,2015.12 (大数据技术丛书) ISBN 978-7-111-52234-8 I. 深- II.耿- III.数据处理软件 IV. TP274 中国版本图书馆CIP数据核字(2015)第280808号 深入理解Spark:核心思想与源码分析 出版发行:机械工业出版社(北京市西城区百万庄大街22号 邮政编码:100037)

JDK源码分析-ArrayList分析

花了两个晚上的时间研究了一下ArrayList的源码, ArrayList 继承自AbstractList 并且实现了List, RandomAccess, Cloneable, Serializable 通过实现这三个接口 就具备了他们的功能 RandomAccess 用来表明其支持快速(通常是固定时间)随机访问 Cloneable可以克隆对象 Serializable 对象序列化就是把一个对象变为二进制的数据流的一种方法,通过对象序列化可以方便地实现对象的传输和存储,Serializable

OkHttp 3.7源码分析(三)——任务队列

OkHttp3.7源码分析文章列表如下: OkHttp源码分析--整体架构 OkHttp源码分析--拦截器 OkHttp源码分析--任务队列 OkHttp源码分析--缓存策略 OkHttp源码分析--多路复用 前面的博客已经提到过,OkHttp的一个高效之处在于在内部维护了一个线程池,方便高效地执行异步请求.本篇博客将详细介绍OkHttp的任务队列机制. 1. 线程池的优点 OkHttp的任务队列在内部维护了一个线程池用于执行具体的网络请求.而线程池最大的好处在于通过线程复用减少非核心任务的损耗