初探RocketMQ架构

news/2025/2/21 3:48:47/文章来源:https://www.cnblogs.com/likeguang/p/18574011

目录
  • 一、概述
  • 二、概览
    • 2.1、部署架构图
      • 1.生产者(Producer)
      • 2.消费者(Consumer)
      • 3.代理服务器(Broker Server)
      • 4.名字服务(Name Server)
    • 2.2 名词解释
      • 1.主题(Topic)
      • 2.标签(Tag)
      • 3.消息(Message)
      • 4.拉取式消费(Pull Consumer)
      • 5.推动式消费(Push Consumer)
      • 6.生产者组(Producer Group)
      • 7.消费者组(Consumer Group)
      • 8.集群消费(Clustering)
      • 9.广播消费(Broadcasting)
      • 10.普通顺序消息(Normal Ordered Message)
      • 11.严格顺序消息(Strictly Ordered Message)
  • 三、原理
    • 3.1 总技术架构图
    • 3.2 启动流程
  • 四、特性
    • 4.1 业务特性
    • 4.2 设计特性
      • 1.订阅与发布
      • 2.消息顺序
      • 3.消息过滤
      • 4.消息可靠性
      • 5.至少一次
      • 6.回溯消费
      • 7.事务消息
      • 8.定时消息
      • 9.消息重试(消费者)
      • 10.消息重投(生产者)
      • 11.流量控制
      • 12.死信队列

一、概述

RocketMQ在MQ中的地位毋庸置疑,java开发者的首选、必会中间件。笔者在深度使用后,结合apache官网、github、源码(版本4.8.0),总结出这个系列文章,供大家参考。本节稍显枯燥,但是有必要读。

自学飞机票:

1.rocketMQ官网

2.github RocketMQ 中文文档

3.参数配置文档

二、概览

RocketMQ是按照典型的生产-消费模型设计的。

2.1、部署架构图

官网架构图黑白色太单调,从网上下了张彩图:

如上图,RocketMQ主要由 Producer生产者、Consumer消费者、Broker代理、NameServer名称服务器 四部分组成。

1.生产者(Producer)

负责发布消息,支持集群部署。Producer通过负载均衡选择Broker集群队列进行消息投递。

2.消费者(Consumer)

负责消费消息,支持集群部署。支持以push推,pull拉两种模式对消息进行消费。群组消费支持:集群方式和广播方式(见2.3)。

3.代理服务器(Broker Server)

消息中转角色,负责存储消息、转发消息。主要包含2个功能:

  • 接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。
  • 存储消息相关的元数据:消费者组consumer Group、消费进度偏移offset、主题Topic、队列消息Message Queue等。

4.名字服务(Name Server)

Name Server是Topic路由的注册中心,支持Broker的动态注册与发现。生产者或消费者能够通过名字服务查找各主题相应的Broker IP列表。多个Namesrv实例组成集群,无状态(每个实例数据一样)。

2.2 名词解释

1.主题(Topic)

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

2.标签(Tag)

为消息设置的标志,用于同一topic下区分不同类型的消息。可以根据topic+Tag实现消息的精细化生产和消费。

3.消息(Message)

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

4.拉取式消费(Pull Consumer)

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

5.推动式消费(Push Consumer)

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

6.生产者组(Producer Group)

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

7.消费者组(Consumer Group)

同一类Consumer的集合,这类Consumer通常消费同一类消息且消费逻辑一致。要注意的是,消费者组的消费者实例必须订阅完全相同的Topic。RocketMQ 支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting)。

8.集群消费(Clustering)

集群消费模式下,一个消息只能被一个Consumer消费。

9.广播消费(Broadcasting)

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

10.普通顺序消息(Normal Ordered Message)

普通顺序消费模式下,消费者通过同一个消费队列收到的消息是有顺序的,不同消息队列收到的消息则可能是无顺序的。(message queue见2.4 消息存储模型)

11.严格顺序消息(Strictly Ordered Message)

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

三、原理

3.1 总技术架构图

3.2 启动流程

四、特性

了了解原理外还必须清晰知道一款软件的的功能特性,以便后期技术选型。

4.1 业务特性

Apache RocketMQ上描述了6个业务特性:

  1. 低延迟
  2. 面向金融(可跟踪)
  3. 行业支撑(万亿级消息验证)
  4. 标准
  5. 大数据友好
  6. 支持大量消息堆积。

4.2 设计特性

Github上描述了12个设计特性。总结的挺好:

1.订阅与发布

消息的发布是指某个生产者向某个topic发送消息;消息的订阅是指某个消费者关注了某个topic中带有某些tag的消息,进而从该topic消费数据。

2.消息顺序

消息有序指的是一类消息消费时,能按照发送的顺序来消费。顺序消息分为全局顺序消息与分区顺序消息,全局顺序是指某个Topic下的所有消息都要保证顺序;部分顺序消息只要保证每一组消息被顺序消费即可。
- 全局顺序
对于指定的一个 Topic,所有消息按照严格的先入先出(FIFO)的顺序进行发布和消费。
适用场景:性能要求不高,所有的消息严格按照 FIFO 原则进行消息发布和消费的场景
- 分区顺序
对于指定的一个 Topic,所有消息根据 sharding key 进行区块分区。 同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费。 Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key 是完全不同的概念。
适用场景:性能要求高,以 sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景。

3.消息过滤

RocketMQ的消费者可以根据Tag进行消息过滤,也支持自定义属性过滤。消息过滤目前是在Broker端实现的,优点是减少了对于Consumer无用消息的网络传输,缺点是增加了Broker的负担、而且实现相对复杂。

4.消息可靠性

RocketMQ支持消息的高可靠,影响消息可靠性的几种情况:

  1. Broker非正常关闭
  2. Broker异常Crash
  3. OS Crash
  4. 机器掉电,但是能立即恢复供电情况
  5. 机器无法开机(可能是cpu、主板、内存等关键设备损坏)
  6. 磁盘设备损坏

1)、2)、3)、4) 四种情况都属于硬件资源可立即恢复情况,RocketMQ在这四种情况下能保证消息不丢,或者丢失少量数据(依赖刷盘方式是同步还是异步)。

5)、6)属于单点故障,且无法恢复,一旦发生,在此单点上的消息全部丢失。RocketMQ在这两种情况下,通过异步复制,可保证99%的消息不丢,但是仍然会有极少量的消息可能丢失。通过同步双写技术可以完全避免单点,同步双写势必会影响性能,适合对消息可靠性要求极高的场合,例如与Money相关的应用。注:RocketMQ从3.0版本开始支持同步双写。

5.至少一次

至少一次(At least Once)指每个消息必须投递一次。Consumer先Pull消息到本地,消费完成后,才向服务器返回ack,如果没有消费一定不会ack消息,所以RocketMQ可以很好的支持此特性。

6.回溯消费

回溯消费是指Consumer已经消费成功的消息,由于业务上需求需要重新消费,要支持此功能,Broker在向Consumer投递成功消息后,消息仍然需要保留。并且重新消费一般是按照时间维度,例如由于Consumer系统故障,恢复后需要重新消费1小时前的数据,那么Broker要提供一种机制,可以按照时间维度来回退消费进度。RocketMQ支持按照时间回溯消费,时间维度精确到毫秒。

7.事务消息

RocketMQ事务消息(Transactional Message)是指应用本地事务和发送消息操作可以被定义到全局事务中,要么同时成功,要么同时失败。RocketMQ的事务消息提供类似 X/Open XA 的分布事务功能,通过事务消息能达到分布式事务的最终一致。

8.定时消息

定时消息(延迟队列)是指消息发送到broker后,不会立即被消费,等待特定时间投递给真正的topic。
broker有配置项messageDelayLevel,默认值为“1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h”,18个level。可以配置自定义messageDelayLevel。注意,messageDelayLevel是broker的属性,不属于某个topic。发消息时,设置delayLevel等级即可:msg.setDelayLevel(level)。level有以下三种情况:

- level == 0,消息为非延迟消息
- 1<=level<=maxLevel,消息延迟特定时间,例如level1,延迟1s
- level > maxLevel,则level
maxLevel,例如level==20,延迟2h

定时消息会暂存在名为SCHEDULE_TOPIC_XXXX的topic中,并根据delayTimeLevel存入特定的queue,queueId = delayTimeLevel – 1,即一个queue只存相同延迟的消息,保证具有相同发送延迟的消息能够顺序消费。broker会调度地消费SCHEDULE_TOPIC_XXXX,将消息写入真实的topic。

需要注意的是,定时消息会在第一次写入和调度写入真实topic时都会计数,因此发送数量、tps都会变高。

9.消息重试(消费者)

Consumer消费消息失败后,要提供一种重试机制,令消息再消费一次。Consumer消费消息失败通常可以认为有以下几种情况:
- 由于消息本身的原因,例如反序列化失败,消息数据本身无法处理(例如话费充值,当前消息的手机号被注销,无法充值)等。这种错误通常需要跳过这条消息,再消费其它消息,而这条失败的消息即使立刻重试消费,99%也不成功,所以最好提供一种定时重试机制,即过10秒后再重试。
- 由于依赖的下游应用服务不可用,例如db连接不可用,外系统网络不可达等。遇到这种错误,即使跳过当前失败的消息,消费其他消息同样也会报错。这种情况建议应用sleep 30s,再消费下一条消息,这样可以减轻Broker重试消息的压力。

RocketMQ会为每个消费组都设置一个Topic名称为“%RETRY%+consumerGroup”的重试队列(这里需要注意的是,这个Topic的重试队列是针对消费组,而不是针对每个Topic设置的),用于暂时保存因为各种异常而导致Consumer端无法消费的消息。考虑到异常恢复起来需要一些时间,会为重试队列设置多个重试级别,每个重试级别都有与之对应的重新投递延时,重试次数越多投递延时就越大。RocketMQ对于重试消息的处理是先保存至Topic名称为“SCHEDULE_TOPIC_XXXX”的延迟队列中,后台定时任务按照对应的时间进行Delay后重新保存至“%RETRY%+consumerGroup”的重试队列中。

10.消息重投(生产者)

生产者在发送消息时,同步消息失败会重投,异步消息有重试,oneway没有任何保证。消息重投保证消息尽可能发送成功、不丢失,但可能会造成消息重复,消息重复在RocketMQ中是无法避免的问题。消息重复在一般情况下不会发生,当出现消息量大、网络抖动,消息重复就会是大概率事件。另外,生产者主动重发、consumer负载变化也会导致重复消息。如下方法可以设置消息重试策略:

- retryTimesWhenSendFailed:同步发送失败重投次数,默认为2,因此生产者会最多尝试发送retryTimesWhenSendFailed + 1次。不会选择上次失败的broker,尝试向其他broker发送,最大程度保证消息不丢。超过重投次数,抛出异常,由客户端保证消息不丢。当出现RemotingException、MQClientException和部分MQBrokerException时会重投。
- retryTimesWhenSendAsyncFailed:异步发送失败重试次数,异步重试不会选择其他broker,仅在同一个broker上做重试,不保证消息不丢。
- retryAnotherBrokerWhenNotStoreOK:消息刷盘(主或备)超时或slave不可用(返回状态非SEND_OK),是否尝试发送到其他broker,默认false。十分重要消息可以开启

11.流量控制

生产者流控,因为broker处理能力达到瓶颈;消费者流控,因为消费能力达到瓶颈。

生产者流控:
- commitLog文件被锁时间超过osPageCacheBusyTimeOutMills时,参数默认为1000ms,返回流控。
- 如果开启transientStorePoolEnable == true,且broker为异步刷盘的主机,且transientStorePool中资源不足,拒绝当前send请求,返回流控。
- broker每隔10ms检查send请求队列头部请求的等待时间,如果超过waitTimeMillsInSendQueue,默认200ms,拒绝当前send请求,返回流控。
- broker通过拒绝send 请求方式实现流量控制。

注意,生产者流控,不会尝试消息重投

消费者流控:
- 消费者本地缓存消息数超过pullThresholdForQueue时,默认1000。
- 消费者本地缓存消息大小超过pullThresholdSizeForQueue时,默认100MB。
- 消费者本地缓存消息跨度超过consumeConcurrentlyMaxSpan时,默认2000。

消费者流控的结果是降低拉取频率。

12.死信队列

死信队列用于处理无法被正常消费的消息。当一条消息初次消费失败,消息队列会自动进行消息重试;达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息,此时,消息队列 不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中。

RocketMQ将这种正常情况下无法被消费的消息称为死信消息(Dead-Letter Message),将存储死信消息的特殊队列称为死信队列(Dead-Letter Queue)。在RocketMQ中,可以通过使用console控制台(官方提供的后台管理WEB界面)对死信队列中的消息进行重发来使得消费者实例再次进行消费。

总结:这12个特性中,需要关注的有:

消息顺序、消息过滤、事务消息、消息重试(消费者)、消息重投(生产者)、流量控制、死信队列。

参考:

RocketMQ架构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/842792.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

库存系统:应用层、领域层、对接层的架构设计

大家好,我是汤师爷~ 大厂对候选人的要求较高,即使是20k薪资的岗位,也期望应聘者能够独立承担工作职责。 对于30-40k薪资的岗位,需要具备独立系统设计和小型架构设计的能力。 技术专家和架构师岗位(30-50k以上)要求应聘者具有带领团队、负责大型系统架构的经验,并且在架构…

分布式锁的实现原理

介绍分布式锁的实现原理。作者:来自 vivo 互联网服务器团队- Xu Yaoming介绍分布式锁的实现原理。 一、分布式锁概述 分布式锁,顾名思义,就是在分布式环境下使用的锁。众所周知,在并发编程中,我们经常需要借助并发控制工具,如 mutex、synchronized 等,来保障线程安全。但…

HyperWorks变形域和控制柄方法

变形域和控制柄方法 使用变形域和控制柄方法进行网格变形时,网格模型被分割成若干个变形子域,位于变形域上的控制柄常常用来控制变形域形状的变化。当控制柄移动时,变形域的形状随之变化,进而影响变形域内部节点位置的分布。变形过程中,网格以一种合乎逻辑的方式变化,即靠…

记录Vue Antd 表格RowSelection刷新列表后缓存问题

起因原来的代码//tsx部分 <BaseTableoptions={tableData.options}columns={tableData.columns}data={tableData.data}/>const selectKeys = ref<string[]>([])// 表格配置const handleRowSelection = {onChange: (selectedRowKeys: string[], selectedRows: IS…

震惊!推荐一款AI驱动的自动化测试神器:TestCraft

在当今快速迭代的软件开发环境中,自动化测试已经成为确保软件质量的重要一环。然而,传统的手动录制和编写测试脚本的方式不仅耗时耗力,还难以跟上敏捷开发的节奏。 本文将为大家介绍一款基于AI技术的自动化测试工具——TestCraft,它凭借其智能化、易用性和高效性,正逐渐成…

信息安全概论复习-2

计算机系统的可靠性和可用性 系统可靠性定义及测量方法硬件的可靠性和完美性软件的可靠性和完美性容错技术和系统,冗余技术冗余类型,4种,硬件软件时间信息容错系统的工作方式 1、自动检查 2、自动切换 3、自动修复 容错系统和部件--系统级容错、部件级容错--就是备用系统、部…

初探RocketMQ消息消费原理(一)

目录一. 消息消费概述二、消费队列负载机制与重平衡1.1 消费队列负载机制与重平衡1.2 并发消费模型1.3 消息消费进度反馈机制 一. 消息消费概述 消息消费以组的模式开展,一个消费组可以包含多个消费者,每个消费组可以订阅多个主题(一般来说不建议),消费组之间有集群模式和…

rust中使用opencv-cuda和yolov

最近公司有个要识别的项目需要计算机识别,于是就找到了opencv来进行,opencv的cuda版本需要自己来进行编译需要去opencv官网下载,我下载的版本是opencv4.10 https://github.com/opencv/opencv/archive/refs/tags/4.10.0.zip 还有需要opencv_contrib-4.10.0和cmake下载 下载之…

rust中使用opencv和cuda

最近公司有个要识别的项目需要计算机识别,于是就找到了opencv来进行,opencv的cuda版本需要自己来进行编译需要去opencv官网下载,我下载的版本是opencv4.10 https://github.com/opencv/opencv/archive/refs/tags/4.10.0.zip 还有需要opencv_contrib-4.10.0和cmake下载 下载之…

视效升级如此简单?零代码实现炫酷管道效果

三维场景视效升级 通过添加管道效果,可以提升整个三维场景的辨识度,尤其是在需要表现水流流向、能源运输、移动路径等场景中。通过设置管道效果,不仅能够清晰表达设计思路,还能为整个场景增添一抹亮色。下面我们就一起来看一下,如何在山海鲸可视化中添加管道效果。1. 管道…

CudaSPONGE之Python接口

本文介绍了高性能GPU分子动力学模拟软件CudaSPONGE的Python API接口,通过官方开发的prips插件,使得我们可以在Python框架下很方便的开发一些分子动力学模拟的Force Wrapper,例如Meta Dynamics中就有很多可以外界的工具,非常方便开发者的二次开发,同时又能够兼顾到性能。技…

行业专家推荐2024年CRM系统Top 5

商业环境瞬息万变,客户关系管理(CRM)系统帮助企业更好地连接客户、理解客户、服务客户,已成为企业不可或缺的战略资产。 企业在选择CRM系统时,应做好充分的市场调查。为了帮助企业更好地把握市场机遇,提升客户体验,本文根据搜索结果和行业专家的评价,推荐2024年各方面排…