Java进阶-RocketMQ-基础

一、架构设计

官方文档-技术架构
RocketMQ源码解析(一)-架构原理

技术架构.jpeg
  • Producer:消息发布的角色,支持分布式集群方式部署。Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。
  • Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。
  • NameServer:NameServer是一个非常简单的Topic路由注册中心,其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:Broker管理、路由信息管理
  • BrokerServer:Broker主要负责消息的存储、投递和查询以及服务高可用保证
部署架构.jpeg

  集群工作流程:

  • 启动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建立连接通道,开始消费消息。

二、消息发送

  Producer发送消息支持3种方式,同步、异步和Oneway

  • 同步发送:客户端提交消息到broker后会等待返回结果,默认方式
  • 异步发送:调用发送接口时会注册一个callback类,发送线程继续其它业务逻辑,Producer在收到broker结果后回调
  • Oneway:Producer提交消息后,无论broker是否正常接收消息都不关心适合于追求高吞吐、能容忍消息丢失的场景,比如日志收集

2.1 Name服务器的均等性

  在Broker启动的时候,其会将自己在本地存储的话题配置文件 (默认位于 $HOME/store/config/topics.json目录) 中的所有话题加载到内存中去,然后会将这些所有的话题全部同步到所有的Name服务器中。与此同时,Broker也会启动一个定时任务,默认每隔 30 秒来执行一次话题全同步:

image.png

2.2 寻找路由信息

  当客户端发送消息的时候,其首先会尝试寻找话题路由信息。即这条消息应该被发送到哪个地方去。客户端在内存中维护了一份和话题相关的路由信息表topicPublishInfoTable,当发送消息的时候,会首先尝试从此表中获取信息。如果此表不存在这条话题的话,那么便会从Name服务器获取路由消息。

image.png

  服务器返回的话题路由信息包括以下内容:

image.png

  每个Broker上面可以绑定多个可写消息队列和多个可读消息队列,客户端根据返回的所有Broker地址列表和每个Broker的可写消息队列列表会在内存中构建一份所有的消息队列列表。之后客户端每次发送消息,都会在消息队列列表上轮循选择队列 (我们假设返回了两个 Broker,每个 Broker 均有 4 个可写消息队列):

image.png

2.3 话题检查

image.png

2.4 整体流程

image.png

2.5 源码解析

Message msg = new Message( "Test", "Hello World".getBytes() );
DefaultMQProducer producer = new DefaultMQProducer();
producer.start();
--------
producer.send(msg);
RocketMQ-Producer.png

RocketMQ 消息发送流程
RocketMQ源码解析(三)-Producer

三、消息存储

  用来存储消息的文件被称之为MappedFile。文件默认创建的大小为1GB,即102410241024=1073741824字节,每个文件的命名是按照总的字节偏移量来命名的

image.png

3.1 文件创建

  当Broker启动的时候,其会将位于存储目录下的所有消息文件加载到一个列表中,当有新的消息到来的时候,其会默认选择列表中的最后一个文件来进行消息的保存。

  RocketMQ提供了一个专门用来实例化MappedFile文件的服务类AllocateMappedFileService。在内存中,也同时维护了一张请求表requestTable和一个优先级请求队列requestQueue当需要创建文件的时候,Broker会创建一个AllocateRequest对象,其包含了文件的路径、大小等信息。然后先将其放入requestTable表中,再将其放入优先级请求队列requestQueue中

  服务类会一直等待优先级队列是否有新的请求到来,如果有,便会从队列中取出请求,然后创建对应的MappedFile,并将请求表requestTable中AllocateRequest对象的字段mappedFile设置上值。最后将AllocateRequest对象上的CountDownLatch的计数器减1 ,以标明此分配申请的MappedFile已经创建完毕了

image.png

  等待MappedFile创建完毕之后,其便会从请求表requestTable中取出并删除表中记录,然后再将其放到MappedFile列表中去。

image.png

3.2 文件初始化

  在MappedFile的构造函数中,其使用了FileChannel类提供的map函数来将磁盘上的这个文件映射到进程地址空间中。然后当通过MappedByteBuffer来读入或者写入文件的时候,磁盘上也会有相应的改动。

3.3 消息写入

  每条消息的存储是按照一个4字节的长度来做界限的,这个长度本身就是整个消息体的长度,当读完这整条消息体的长度之后,下一次再取出来的一个4字节的数字,便又是下一条消息的长度。

image.png
image.png

  前两位是4字节的长度和4字节的MAGICCODE,MAGICCODE的可选值有:

  • CommitLog.MESSAGE_MAGIC_CODE
  • CommitLog.BLANK_MAGIC_CODE

  当这个文件有能力容纳这条消息体的情况下,其便会存储MESSAGE_MAGIC_CODE值;当这个文件没有能力容纳这条消息体的情况下,其便会存储BLANK_MAGIC_CODE值。所以这个MAGICCODE是用来界定这是空消息还是一条正常的消息

3.4 消息刷盘

  • 同步刷盘
  • 异步刷盘

四、消息接受

  消费者客户端与Broker服务器进行沟通的整体流程如下:

image.png

  RocketMQ管理消息的单位不是话题,而是队列
  客户端有两种消费模式,一种是广播模式,另外一种是集群模式。

  集群模式:

  • 平均分配策略
  • 平均分配轮循策略
  • 一致性哈希策略

4.1 Broker消费队列文件

  消息往Broker存储就是在向CommitLog消息文件中写入数据的一个过程。在Broker启动过程中,其会启动一个叫做ReputMessageService的服务,这个服务每隔1秒会检查一下这个CommitLog是否有新的数据写入。ReputMessageService自身维护了一个偏移量reputFromOffset,用以对比和CommitLog文件中的消息总偏移量的差距。当这两个偏移量不同的时候,就代表有新的消息到来了。

  commitLog文件夹下面存放的是完整的消息,来一条消息,向文件中追加一条消息。同时,根据这一条消息属于TopicTest话题下的哪一个队列,又会往相应的consumequeue文件下的相应消费队列文件中追加消息的偏移量、消息大小和标签码。

image.png
image.png

4.2 消息队列偏移量

  针对同一话题,在集群模式下,由于每个客户端所消费的消息队列不同,所以每个消息队列已经消费到哪里的消费偏移量是记录在Broker服务器端的。而在广播模式下,由于每个客户端分配消费这个话题的所有消息队列,所以每个消息队列已经消费到哪里的消费偏移量是记录在客户端本地的。

  集群模式:

image.png

  广播模式:

image.png

4.3 拉取消息

  客户端和Broker服务器端完整拉取消息的流程图如下:

image.png

4.3 消费消息

  并发消费:

image.png

  有序消费:

  RocketMQ的有序消费主要依靠两把锁,一把是维护在Broker端,一把维护在消费者客户端。在有序消费的时候,Broker需要确保任何一个队列在任何时候都只有一个客户端在消费它,都在被一个客户端所锁定

image.png

  RocketMQ的消息树是用TreeMap实现的,其内部基于消息偏移量维护了消息的有序性。每次消费请求都会从消息树中拿取偏移量最小的几条消息 (默认为1条)给用户,以此来达到有序消费的目的

image.png

五、消息过滤

  • 标签匹配
  • SQL匹配
  • 自定义匹配
image.png
image.png
image.png

六、消息索引

  • 根据键查询消息
  • 根据ID(偏移量)查询消息
  • 根据唯一键查询消息
  • 根据消息队列偏移量查询消息

  ID (偏移量) 查询:

image.png

  消息队列偏移量查询:

image.png

  消息索引服务:

  每当一条消息发送过来之后,其会封装为一个DispatchRequest来下发给各个转发服务,而CommitLogDispatcherBuildIndex构建索引服务便是其中之一。

  • 前40个字节存放固定的索引头信息,包含了存放在这个索引文件中的消息的最小/大存储时间、最小/大偏移量等状况
  • 中间一段存储了500万个哈希槽位,每个槽内部存储的是索引文件的地址 (索引槽)
  • 最后一段存储了2000万个索引内容信息,是实际的索引信息存储的地方。每一个槽位存储了这条消息的键哈希值、存储偏移量、存储时间戳与下一个索引槽地址
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容