关于RocketMQ

关于RocketMQ

一、RocketMQ集群架构

关于RocketMQ_第1张图片

二、RocketMQ角色

  1. Topic:区分消息的种类;一个发送者可以发送消息给一个或者多个Topic;一个消息的接收者可以订阅一个或者多个Topic消息。我们之前的测试案例中,Topic是什么?topic=‘TopicTest’。现在你能看懂我们之前在broker.conf中添加的autoCreateTopicEnable=true这个属性的用处了吗?
  2. Message Queue:相当于是Topic的分区;用于并行发送和接收消息。在我们之前的测试案例中,一个queueId就代表了一个MessageQueue。有哪些queueId? 0,1,2,3四个MessageQueue,你都找到了吗?
  3. Producer:消息的发送者;举例:发信者
  4. Consumer:消息接收者;举例:收信者
  5. Broker:暂存和传输消息;举例:邮局
  6. NameServer:管理Broker;举例:各个邮局的管理机构

阿里云rocketmq跟开源版rocketmq的区别

阿里云rocketmq 开源版rocketmq
可靠性 -同步刷盘-同步双写-超3份数据副本-99.99999999% -同步刷盘-异步刷盘
开源版rocketmq -非常好,99.95%- Always Writable
横向扩展能力 -支持平滑扩展-支持平滑扩展QPS 支持
Low Latency 支持 不支持
消费模型 Push / Pull Push / Pull
定时消息 支持(可精确到秒级) 支持(只支持18个固定 Level )
事务消息 支持 不支持
顺序消息 支持 支持
全链路消息轨迹 支持 不支持
消息堆积能力 百亿级别不影响性能 百亿级别影响性能
消息堆积查询 支持 支持
消息回溯 支持 支持
消息重试 支持 支持
消息重试 支持 支持
性能(常规) 非常好百万级QPS 非常好十万级 QPS
性能(万级Topic场景) 非常好百万级QPS 非常好十万级QPS
性能(海量消息 非常好 非常好

1、主题(Topic)

定义

  • 定义数据的分类隔离: 在 Apache RocketMQ 的方案设计中,建议将不同业务类型的数据拆分到不同的主题中管理,通过主题实现存储的隔离性和订阅隔离性。
  • 定义数据的身份和权限: Apache RocketMQ 的消息本身是匿名无身份的,同一分类的消息使用相同的主题来做身份识别和权限管理。

模型关系

在整个 Apache RocketMQ 的领域模型中,主题所处的流程和位置如下:

关于RocketMQ_第2张图片

主题是 Apache RocketMQ 的顶层存储,所有消息资源的定义都在主题内部完成,但主题是一个逻辑概念,并不是实际的消息容器。

主题内部由多个队列组成,消息的存储和水平扩展能力最终是由队列实现的;并且针对主题的所有约束和属性设置,最终也是通过主题内部的队列来实现。

内部属性

主题名称

  • 定义:主题的名称,用于标识主题,主题名称集群内全局唯一。
  • 取值:由用户创建主题时定义。
  • 约束:请参见参数限制。

队列列表

  • 定义:队列作为主题的组成单元,是消息存储的实际容器,一个主题内包含一个或多个队列,消息实际存储在主题的各队列内。更多信息,请参见队列(MessageQueue)。
  • 取值:系统根据队列数量给主题分配队列,队列数量创建主题时定义。
  • 约束:一个主题内至少包含一个队列。

消息类型

  • 定义:主题所支持的消息类型。
  • 取值:创建主题时选择消息类型。Apache RocketMQ 支持的主题类型如下:
    • Normal:普通消息,消息本身无特殊语义,消息之间也没有任何关联。
    • FIFO:顺序消息,Apache RocketMQ 通过消息分组MessageGroup标记一组特定消息的先后顺序,可以保证消息的投递顺序严格按照消息发送时的顺序。
    • Delay:定时/延时消息,通过指定延时时间控制消息生产后不要立即投递,而是在延时间隔后才对消费者可见。
    • Transaction:事务消息,Apache RocketMQ 支持分布式事务消息,支持应用数据库更新和消息调用的事务一致性保障。
  • 约束:每个主题只支持一种消息类型。

行为约束

消息类型强制校验

Apache RocketMQ 5.x版本将消息类型拆分到主题中进行独立运维和处理,因此系统会对发送的消息类型和主题定的消息类型进行强制校验,若校验不通过,则消息发送请求会被拒绝,并返回类型不匹配异常。校验原则如下:

  • 消息类型必须一致发送的消息的类型,必须和目标主题定义的消息类型一致。
  • 主题类型必须单一每个主题只支持一种消息类型,不允许将多种类型的消息发送到同一个主题中。

常见错误使用场景

  • 发送的消息类型不匹配例如,创建主题时消息类型定义为顺序消息,发送消息时发送事务消息到该主题中,此时消息发送请求会被拒绝,并返回类型不匹配异常。
  • 单一消息主题混用例如,创建主题时消息类型定义为普通消息,发送消息时同时发送普通消息和顺序消息到该主题中,则顺序消息的发送请求会被拒绝,并返回类型不匹配异常。

版本兼容性

消息类型的强制校验,仅针对 Apache RocketMQ 服务端5.x版本生效。 Apache RocketMQ 服务端4.x和3.x历史版本的SDK不支持强制校验,您需要自己保证消息类型一致。 如果您使用的服务端版本为历史版本,建议您升级到 Apache RocketMQ 服务端5.x版本。

使用建议

按照业务分类合理拆分主题

Apache RocketMQ 的主题拆分设计应遵循大类统一原则,即将相同业务域内同一功能属性的消息划分为同一主题。拆分主题时,您可以从以下角度考虑拆分粒度:

  • 消息类型是否一致:不同类型的消息,如顺序消息和普通消息需要使用不同的主题。
  • 消息业务是否关联:如果业务没有直接关联,比如,淘宝交易消息和盒马物流消息没有业务交集,需要使用不同的消息主题;同样是淘宝交易消息,女装类订单和男装类订单可以使用同一个订单。当然,如果业务量较大或其他子模块应用处理业务时需要进一步拆分订单类型,您也可以将男装订单和女装订单的消息拆分到两个主题中。
  • 消息量级是否一样:数量级不同或时效性不同的业务消息建议使用不同的主题,例如某些业务消息量很小但是时效性要求很强,如果跟某些万亿级消息量的业务使用同一个主题,会增加消息的等待时长。

正确拆分示例: 线上商品购买场景下,订单交易如订单创建、支付、取消等流程消息使用一个主题,物流相关消息使用一个主题,积分管理相关消息使用一个主题。

错误拆分示例:

  • 拆分粒度过粗:会导致业务隔离性差,不利于独立运维和故障处理。例如,所有交易消息和物流消息都共用一个主题。
  • 拆分粒度过细:会消耗大量主题资源,造成系统负载过重。例如,按照用户ID区分,每个用户ID使用一个主题。

单一主题只收发一种类型消息,避免混用

Apache RocketMQ 主题的设计原则为通过主题隔离业务,不同业务逻辑的消息建议使用不同的主题。同一业务逻辑消息的类型都相同,因此,对于指定主题,应该只收发同一种类型的消息。

主题管理尽量避免自动化机制

在 Apache RocketMQ 架构中,主题属于顶层资源和容器,拥有独立的权限管理、可观测性指标采集和监控等能力,创建和管理主题会占用一定的系统资源。因此,生产环境需要严格管理主题资源,请勿随意进行增、删、改、查操作。

Apache RocketMQ 虽然提供了自动创建主题的功能,但是建议仅在测试环境使用,生产环境请勿打开,避免产生大量垃圾主题,无法管理和回收并浪费系统资源。

2、队列(MessageQueue)

本文介绍 Apache RocketMQ 中队列(MessageQueue)的定义、模型关系、内部属性、版本兼容性及使用建议。

定义

队列是 Apache RocketMQ 中消息存储和传输的实际容器,也是 Apache RocketMQ 消息的最小存储单元。 Apache RocketMQ 的所有主题都是由多个队列组成,以此实现队列数量的水平拆分和队列内部的流式存储。

队列的主要作用如下:

  • 存储顺序性

    队列天然具备顺序性,即消息按照进入队列的顺序写入存储,同一队列间的消息天然存在顺序关系,队列头部为最早写入的消息,队列尾部为最新写入的消息。消息在队列中的位置和消息之间的顺序通过位点(Offset)进行标记管理。

  • 流式操作语义

    Apache RocketMQ 基于队列的存储模型可确保消息从任意位点读取任意数量的消息,以此实现类似聚合读取、回溯读取等特性,这些特性是RabbitMQ、ActiveMQ等非队列存储模型不具备的。

模型关系

在整个 Apache RocketMQ 的领域模型中,队列所处的流程和位置如下:关于RocketMQ_第3张图片

Apache RocketMQ 默认提供消息可靠存储机制,所有发送成功的消息都被持久化存储到队列中,配合生产者和消费者客户端的调用可实现至少投递一次的可靠性语义。

Apache RocketMQ 队列模型和Kafka的分区(Partition)模型类似。在 Apache RocketMQ 消息收发模型中,队列属于主题的一部分,虽然所有的消息资源以主题粒度管理,但实际的操作实现是面向队列。例如,生产者指定某个主题,向主题内发送消息,但实际消息发送到该主题下的某个队列中。

Apache RocketMQ 中通过修改队列数量,以此实现横向的水平扩容和缩容。

内部属性

读写权限

  • 定义:当前队列是否可以读写数据。

  • 取值:由服务端定义,枚举值如下

    • 6:读写状态,当前队列允许读取消息和写入消息。
    • 4:只读状态,当前队列只允许读取消息,不允许写入消息。
    • 2:只写状态,当前队列只允许写入消息,不允许读取消息。
    • 0:不可读写状态,当前队列不允许读取消息和写入消息。
  • 约束:队列的读写权限属于运维侧操作,不建议频繁修改。

行为约束

每个主题下会由一到多个队列来存储消息,每个主题对应的队列数与消息类型以及实例所处地域(Region)相关,队列数暂不支持修改。

版本兼容性

队列的名称属性在 Apache RocketMQ 服务端的不同版本中有如下差异:

  • 服务端3.x/4.x版本:队列名称由{主题名称}+{BrokerID}+{QueueID}三元组组成,和物理节点绑定。
  • 服务端5.x版本:队列名称为一个集群分配的全局唯一的字符串组成,和物理节点解耦。

因此,在开发过程中,建议不要对队列名称做任何假设和绑定。如果您在代码中自定义拼接队列名称并和其他操作进行绑定,一旦服务端版本升级,可能会出现队列名称无法解析的兼容性问题。

使用建议

按照实际业务消耗设置队列数

Apache RocketMQ 的队列数可在创建主题或变更主题时设置修改,队列数量的设置应遵循少用够用原则,避免随意增加队列数量。

主题内队列数过多可能对导致如下问题:

  • 集群元数据膨胀

    Apache RocketMQ 会以队列粒度采集指标和监控数据,队列过多容易造成管控元数据膨胀。

  • 客户端压力过大

    Apache RocketMQ 的消息读写都是针对队列进行操作,队列过多容易产生空轮询请求,增加系统负荷。

常见队列增加场景

  • 需要增加队列实现物理节点负载均衡

    Apache RocketMQ 每个主题的多个队列可以分布在不同的服务节点上,在集群水平扩容增加节点后,为了保证集群流量的负载均衡,建议在新的服务节点上新增队列,或将旧的队列迁移到新的服务节点上。

  • 需要增加队列实现顺序消息性能扩展

    在 Apache RocketMQ 服务端4.x版本中,顺序消息的顺序性在队列内生效的,因此顺序消息的并发度会在一定程度上受队列数量的影响,因此建议仅在系统性能瓶颈时再增加队列。

3、消息(Message)

定义

消息是 Apache RocketMQ 中的最小数据传输单元。生产者将业务数据的负载和拓展属性包装成消息发送到 Apache RocketMQ 服务端,服务端按照相关语义将消息投递到消费端进行消费。

Apache RocketMQ 的消息模型具备如下特点:

  • 消息不可变性

    消息本质上是已经产生并确定的事件,一旦产生后,消息的内容不会发生改变。即使经过传输链路的控制也不会发生变化,消费端获取的消息都是只读消息视图。

  • 消息持久化

    Apache RocketMQ 会默认对消息进行持久化,即将接收到的消息存储到 Apache RocketMQ 服务端的存储文件中,保证消息的可回溯性和系统故障场景下的可恢复性。

模型关系

在整个 Apache RocketMQ 的领域模型中,消息所处的流程和位置如下:关于RocketMQ_第4张图片

  1. 消息由生产者初始化并发送到Apache RocketMQ 服务端。
  2. 消息按照到达Apache RocketMQ 服务端的顺序存储到队列中。
  3. 消费者按照指定的订阅关系从Apache RocketMQ 服务端中获取消息并消费。

消息内部属性

系统保留属性

主题名称

  • 定义:当前消息所属的主题的名称。集群内全局唯一。更多信息,请参见主题(Topic)。
  • 取值:从客户端SDK接口获取。

消息类型

  • 定义:当前消息的类型。
  • 取值:从客户端SDK接口获取。Apache RocketMQ 支持的消息类型如下:
    • Normal:普通消息,消息本身无特殊语义,消息之间也没有任何关联。
    • FIFO:顺序消息,Apache RocketMQ 通过消息分组MessageGroup标记一组特定消息的先后顺序,可以保证消息的投递顺序严格按照消息发送时的顺序。
    • Delay:定时/延时消息,通过指定延时时间控制消息生产后不要立即投递,而是在延时间隔后才对消费者可见。
    • Transaction:事务消息,Apache RocketMQ 支持分布式事务消息,支持应用数据库更新和消息调用的事务一致性保障。

消息队列

  • 定义:实际存储当前消息的队列。更多信息,请参见队列(MessageQueue)。
  • 取值:由服务端指定并填充。

消息位点

  • 定义:当前消息存储在队列中的位置。更多信息,请参见消费进度原理。
  • 取值:由服务端指定并填充。取值范围:0~long.Max。

消息ID

  • 定义:消息的唯一标识,集群内每条消息的ID全局唯一。
  • 取值:生产者客户端系统自动生成。固定为数字和大写字母组成的32位字符串。

索引Key列表(可选)

  • 定义:消息的索引键,可通过设置不同的Key区分消息和快速查找消息。
  • 取值:由生产者客户端定义。

过滤标签Tag(可选)

  • 定义:消息的过滤标签。消费者可通过Tag对消息进行过滤,仅接收指定标签的消息。
  • 取值:由生产者客户端定义。
  • 约束:一条消息仅支持设置一个标签。

定时时间(可选)

  • 定义:定时场景下,消息触发延时投递的毫秒级时间戳。更多信息,请参见定时/延时消息。
  • 取值:由消息生产者定义。
  • 约束:最大可设置定时时长为40天。

消息发送时间

  • 定义:消息发送时,生产者客户端系统的本地毫秒级时间戳。
  • 取值:由生产者客户端系统填充。
  • 说明:客户端系统时钟和服务端系统时钟可能存在偏差,消息发送时间是以客户端系统时钟为准。

消息保存时间戳

  • 定义:消息在Apache RocketMQ 服务端完成存储时,服务端系统的本地毫秒级时间戳。 对于定时消息和事务消息,消息保存时间指的是消息生效对消费方可见的服务端系统时间。

  • 取值:由服务端系统填充。

  • 说明:客户端系统时钟和服务端系统时钟可能存在偏差,消息保留时间是以服务端系统时钟为准。

消费重试次数

  • 定义:消息消费失败后,Apache RocketMQ 服务端重新投递的次数。每次重试后,重试次数加1。更多信息,请参见消费重试。
  • 取值:由服务端系统标记。首次消费,重试次数为0;消费失败首次重试时,重试次数为1。

业务自定义属性

  • 定义:生产者可以自定义设置的扩展信息。
  • 取值:由消息生产者自定义,按照字符串键值对设置。

消息负载

  • 定义:业务消息的实际报文数据。
  • 取值:由生产者负责序列化编码,按照二进制字节传输。
  • 约束:请参见参数限制。

行为约束

消息大小不得超过其类型所对应的限制,否则消息会发送失败。

系统默认的消息最大限制如下:

  • 普通和顺序消息:4 MB
  • 事务和定时或延时消息:64 KB

使用建议

单条消息不建议传输超大负载

作为一款消息中间件产品,Apache RocketMQ 一般传输的是都是业务事件数据。单个原子消息事件的数据大小需要严格控制,如果单条消息过大容易造成网络传输层压力,不利于异常重试和流量控制。

生产环境中如果需要传输超大负载,建议按照固定大小做报文拆分,或者结合文件存储等方法进行传输。

消息中转时做好不可变设计

Apache RocketMQ 服务端5.x版本中,消息本身不可编辑,消费端获取的消息都是只读消息视图。 但在历史版本3.x和4.x版本中消息不可变性没有强约束,因此如果您需要在使用过程中对消息进行中转操作,务必将消息重新初始化。

  • 正确使用示例如下:

    Message m = Consumer.receive();Message m2= MessageBuilder.buildFrom(m);Producer.send(m2);
    
  • 错误使用示例如下:

    Message m = Consumer.receive();m.update()Producer.send(m);
    

4、生产者(Producer)

本文介绍 Apache RocketMQ 中生产者(Producer)的定义、模型关系、内部属性、版本兼容性及使用建议。

定义

生产者是 Apache RocketMQ 系统中用来构建并传输消息到服务端的运行实体。

生产者通常被集成在业务系统中,将业务消息按照要求封装成 Apache RocketMQ 的消息(Message)并发送至服务端。

在消息生产者中,可以定义如下传输行为:

  • 发送方式:生产者可通过API接口设置消息发送的方式。Apache RocketMQ 支持同步传输和异步传输。
  • 批量发送:生产者可通过API接口设置消息批量传输的方式。例如,批量发送的消息条数或消息大小。
  • 事务行为:Apache RocketMQ 支持事务消息,对于事务消息需要生产者配合进行事务检查等行为保障事务的最终一致性。具体信息,请参见事务消息。

生产者和主题的关系为多对多关系,即同一个生产者可以向多个主题发送消息,对于平台类场景如果需要发送消息到多个主题,并不需要创建多个生产者;同一个主题也可以接收多个生产者的消息,以此可以实现生产者性能的水平扩展和容灾。 关于RocketMQ_第5张图片

模型关系

在 Apache RocketMQ 的领域模型中,生产者的位置和流程如下:关于RocketMQ_第6张图片

  1. 消息由生产者初始化并发送到Apache RocketMQ 服务端。
  2. 消息按照到达Apache RocketMQ 服务端的顺序存储到主题的指定队列中。
  3. 消费者按照指定的订阅关系从Apache RocketMQ 服务端中获取消息并消费。

内部属性

客户端ID

  • 定义:生产者客户端的标识,用于区分不同的生产者。集群内全局唯一。
  • 取值:客户端ID由Apache RocketMQ 的SDK自动生成,主要用于日志查看、问题定位等运维场景,不支持修改。

通信参数

  • 接入点信息 (必选) :连接服务端的接入地址,用于识别服务端集群。 接入点必须按格式配置,建议使用域名,避免使用IP地址,防止节点变更无法进行热点迁移。
  • 身份认证信息 (可选) :客户端用于身份验证的凭证信息。 仅在服务端开启身份识别和认证时需要传输。
  • 请求超时时间 (可选) :客户端网络请求调用的超时时间。取值范围和默认值,请参见参数限制。

预绑定主题列表

  • 定义:Apache RocketMQ 的生产者需要将消息发送到的目标主题列表,主要作用如下:

    • 事务消息 (必须设置) :事务消息场景下,生产者在故障、重启恢复时,需要检查事务消息的主题中是否有未提交的事务消息。避免生产者发送新消息后,主题中的旧事务消息一直处于未提交状态,造成业务延迟。

    • 非事务消息 (建议设置) :服务端会在生产者初始化时根据预绑定主题列表,检查目标主题的访问权限和合法性,而不需要等到应用启动后再检查。

      若未设置,或后续消息发送的目标主题动态变更, Apache RocketMQ 会对目标主题进行动态补充检验。

  • 约束:对于事务消息,预绑定列表必须设置,且需要和事务检查器一起配合使用。

事务检查器

  • 定义:Apache RocketMQ 的事务消息机制中,为保证异常场景下事务的最终一致性,生产者需要主动实现事务检查器的接口。具体信息,请参见事务消息。
  • 发送事务消息时,事务检查器必须设置,且需要和预绑定主题列表一起配合使用。

发送重试策略

  • 定义: 生产者在消息发送失败时的重试策略。具体信息,请参见消息发送重试机制。

版本兼容性

Apache RocketMQ 服务端5.x版本开始,生产者是匿名的,无需管理生产者分组(ProducerGroup);对于历史版本服务端3.x和4.x版本,已经使用的生产者分组可以废弃无需再设置,且不会对当前业务产生影响。

使用建议

不建议单一进程创建大量生产者

Apache RocketMQ 的生产者和主题是多对多的关系,支持同一个生产者向多个主题发送消息。对于生产者的创建和初始化,建议遵循够用即可、最大化复用原则,如果有需要发送消息到多个主题的场景,无需为每个主题都创建一个生产者。

不建议频繁创建和销毁生产者

Apache RocketMQ 的生产者是可以重复利用的底层资源,类似数据库的连接池。因此不需要在每次发送消息时动态创建生产者,且在发送结束后销毁生产者。这样频繁的创建销毁会在服务端产生大量短连接请求,严重影响系统性能。

  • 正确示例

    Producer p = ProducerBuilder.build();for (int i =0;i<n;i++){    Message m= MessageBuilder.build();    p.send(m); }p.shutdown();
    
  • 典型错误示例

    for (int i =0;i<n;i++){    Producer p = ProducerBuilder.build();    Message m= MessageBuilder.build();    p.send(m);    p.shutdown();  }
    

5、消费者分组(ConsumerGroup)

本文介绍 Apache RocketMQ 中消费者分组(ConsumerGroup)的定义、模型关系、内部属性、行为约束、版本兼容性及使用建议。

定义

消费者分组是 Apache RocketMQ 系统中承载多个消费行为一致的消费者的负载均衡分组。

和消费者不同,消费者分组并不是运行实体,而是一个逻辑资源。在 Apache RocketMQ 中,通过消费者分组内初始化多个消费者实现消费性能的水平扩展以及高可用容灾。

在消费者分组中,统一定义以下消费行为,同一分组下的多个消费者将按照分组内统一的消费行为和负载均衡策略消费消息。

  • 订阅关系:Apache RocketMQ 以消费者分组的粒度管理订阅关系,实现订阅关系的管理和追溯。具体信息,请参见订阅关系(Subscription)。
  • 投递顺序性:Apache RocketMQ 的服务端将消息投递给消费者消费时,支持顺序投递和并发投递,投递方式在消费者分组中统一配置。具体信息,请参见顺序消息。
  • 消费重试策略: 消费者消费消息失败时的重试策略,包括重试次数、死信队列设置等。具体信息,请参见消费重试。

模型关系

在 Apache RocketMQ 的领域模型中,消费者分组的位置和流程如下:关于RocketMQ_第7张图片

  1. 消息由生产者初始化并发送到Apache RocketMQ 服务端。
  2. 消息按照到达Apache RocketMQ 服务端的顺序存储到主题的指定队列中。
  3. 消费者按照指定的订阅关系从Apache RocketMQ 服务端中获取消息并消费。

内部属性

消费者分组名称

  • 定义:消费者分组的名称,用于区分不同的消费者分组。集群内全局唯一。
  • 取值:消费者分组由用户设置并创建。具体命名规范,请参见参数限制。

投递顺序性

  • 定义:消费者消费消息时,Apache RocketMQ 向消费者客户端投递消息的顺序。

    根据不同的消费场景,Apache RocketMQ 提供顺序投递和并发投递两种方式。具体信息,请参见顺序消息。

  • 取值:默认投递方式为并发投递。

消费重试策略

  • 定义:消费者消费消息失败时,系统的重试策略。消费者消费消息失败时,系统会按照重试策略,将指定消息投递给消费者重新消费。具体信息,请参见消费重试。
  • 取值:重试策略包括:
    • 最大重试次数:表示消息可以重新被投递的最大次数,超过最大重试次数还没被成功消费,消息将被投递至死信队列或丢弃。
    • 重试间隔:Apache RocketMQ 服务端重新投递消息的间隔时间。 最大重试次数和重试间隔的取值范围及默认值,请参见参数限制。
  • 约束:重试间隔仅在PushConsumer消费类型下有效。

订阅关系

  • 定义:当前消费者分组关联的订阅关系集合。包括消费者订阅的主题,以及消息的过滤规则等。订阅关系由消费者动态注册到消费者分组中,Apache RocketMQ 服务端会持久化订阅关系并匹配消息的消费进度。更多信息,请参见订阅关系(Subscription)。

行为约束

在 Apache RocketMQ 领域模型中,消费者的管理通过消费者分组实现,同一分组内的消费者共同分摊消息进行消费。因此,为了保证分组内消息的正常负载和消费,

Apache RocketMQ 要求同一分组下的所有消费者以下消费行为保持一致:

  • 投递顺序
  • 消费重试策略

版本兼容性

如行为约束中所述,同一分组内所有消费者的投递顺序和消费重试策略需要保持一致。

  • Apache RocketMQ 服务端5.x版本:上述消费者的消费行为从关联的消费者分组中统一获取,因此,同一分组内所有消费者的消费行为必然是一致的,客户端无需关注。
  • Apache RocketMQ 服务端3.x/4.x历史版本:上述消费逻辑由消费者客户端接口定义,因此,您需要自己在消费者客户端设置时保证同一分组下的消费者的消费行为一致。

若您使用 Apache RocketMQ 服务端5.x版本,客户端使用历史版本SDK,则消费者的消费逻辑以消费者客户端接口的设置为准。

使用建议

按照业务合理拆分分组

Apache RocketMQ 的消费者和主题是多对多的关系,对于消费者分组的拆分设计,建议遵循以下原则:

  • 消费者的投递顺序一致:同一消费者分组下所有消费者的消费投递顺序是相同的,统一都是顺序投递或并发投递,不同业务场景不能混用消费者分组。
  • 消费者业务类型一致:一般消费者分组和主题对应,不同业务域对消息消费的要求不同,例如消息过滤属性、消费重试策略不同。因此,不同业务域主题的消费建议使用不同的消费者分组,避免一个消费者分组消费超过10个主题。

消费者分组管理尽量避免自动化机制

在 Apache RocketMQ 架构中,消费分组属于状态管理类的逻辑资源,每个消费分组都会涉及关联的消费状态、堆积信息、可观测指标和监控采集数据。因此,生产环境需要严格管理消费者分组资源,请勿随意进行增、删、改、查操作。

Apache RocketMQ 虽然提供了自动创建消费者分组的功能,但是建议仅在测试环境使用,生产环境请勿打开,避免产生大量消费者分组,无法管理和回收,且浪费系统资源。

6、消费者(Consumer)

本文介绍 Apache RocketMQ 中消费者(Consumer)的定义、模型关系、内部属性、行为约束、版本兼容性及使用建议。

定义

消费者是 Apache RocketMQ 中用来接收并处理消息的运行实体。 消费者通常被集成在业务系统中,从 Apache RocketMQ 服务端获取消息,并将消息转化成业务可理解的信息,供业务逻辑处理。

在消息消费端,可以定义如下传输行为:

  • 消费者身份:消费者必须关联一个指定的消费者分组,以获取分组内统一定义的行为配置和消费状态。
  • 消费者类型:Apache RocketMQ 面向不同的开发场景提供了多样的消费者类型,包括PushConsumer类型、SimpleConsumer类型、PullConsumer类型(仅推荐流处理场景使用)等。具体信息,请参见消费者分类。
  • 消费者本地运行配置:消费者根据不同的消费者类型,控制消费者客户端本地的运行配置。例如消费者客户端的线程数,消费并发度等,实现不同的传输效果。

模型关系

在 Apache RocketMQ 的领域模型中,消费者的位置和流程如下:关于RocketMQ_第8张图片

  1. 消息由生产者初始化并发送到Apache RocketMQ 服务端。
  2. 消息按照到达Apache RocketMQ 服务端的顺序存储到主题的指定队列中。
  3. 消费者按照指定的订阅关系从Apache RocketMQ 服务端中获取消息并消费。

内部属性

消费者分组名称

  • 定义:当前消费者关联的消费者分组名称,消费者必须关联到指定的消费者分组,通过消费者分组获取消费行为。更多信息,请参见消费者分组(ConsumerGroup)。
  • 取值:消费者分组为Apache RocketMQ 的逻辑资源,需要您提前通过控制台或OpenAPI创建。具体命名格式,请参见使用限制。

客户端ID

  • 定义:消费者客户端的标识,用于区分不同的消费者。集群内全局唯一。
  • 取值:客户端ID由Apache RocketMQ 的SDK自动生成,主要用于日志查看、问题定位等运维场景,不支持修改。

通信参数

  • 接入点信息 (必选) :连接服务端的接入地址,用于识别服务端集群。 接入点必须按格式配置,建议使用域名,避免使用IP地址,防止节点变更无法进行热点迁移。
  • 身份认证信息 (可选) :客户端用于身份验证的凭证信息。 仅在服务端开启身份识别和认证时需要传输。
  • 请求超时时间 (可选) :客户端网络请求调用的超时时间。取值范围和默认值,请参见参数限制。

预绑定订阅关系列表

  • 定义:指定消费者的订阅关系列表。 Apache RocketMQ 服务端可在消费者初始化阶段,根据预绑定的订阅关系列表对目标主题进行权限及合法性校验,无需等到应用启动后才能校验。

  • 取值:建议在消费者初始化阶段明确订阅关系即要订阅的主题列表,若未设置,或订阅的主题动态变更,Apache RocketMQ 会对目标主题进行动态补充校验。

消费监听器

  • 定义:Apache RocketMQ 服务端将消息推送给消费者后,消费者调用消息消费逻辑的监听器。
  • 取值:由消费者客户端本地配置。
  • 约束:使用PushConsumer类型的消费者消费消息时,消费者客户端必须设置消费监听器。消费者类型的具体信息,请参见消费者分类。

行为约束

在 Apache RocketMQ 领域模型中,消费者的管理通过消费者分组实现,同一分组内的消费者共同分摊消息进行消费。因此,为了保证分组内消息的正常负载和消费,

Apache RocketMQ 要求同一分组下的所有消费者以下消费行为保持一致:

  • 投递顺序
  • 消费重试策略

版本兼容性

如行为约束中所述,同一分组内所有消费者的投递顺序和消费重试策略需要保持一致。

  • Apache RocketMQ 服务端5.x版本:上述消费者的消费行为从关联的消费者分组中统一获取,因此,同一分组内所有消费者的消费行为必然是一致的,客户端无需关注。
  • Apache RocketMQ 服务端3.x/4.x历史版本:上述消费逻辑由消费者客户端接口定义,因此,您需要自己在消费者客户端设置时保证同一分组下的消费者的消费行为一致。

若您使用 Apache RocketMQ 服务端5.x版本,客户端使用历史版本SDK,则消费者的消费逻辑以消费者客户端接口的设置为准。

使用建议

不建议在单一进程内创建大量消费者

Apache RocketMQ 的消费者在通信协议层面支持非阻塞传输模式,网络通信效率较高,并且支持多线程并发访问。因此,大部分场景下,单一进程内同一个消费分组只需要初始化唯一的一个消费者即可,开发过程中应避免以相同的配置初始化多个消费者。

不建议频繁创建和销毁消费者

Apache RocketMQ 的消费者是可以重复利用的底层资源,类似数据库的连接池。因此不需要在每次接收消息时动态创建消费者,且在消费完成后销毁消费者。这样频繁地创建销毁会在服务端产生大量短连接请求,严重影响系统性能。

  • 正确示例

    Consumer c = ConsumerBuilder.build();for (int i =0;i<n;i++){      Message m= c.receive();      //process message    }c.shutdown();
    
  • 典型错误示例

    for (int i =0;i<n;i++){    Consumer c = ConsumerBuilder.build();    Message m= c.receive();    //process message    c.shutdown();  }
    

7、订阅关系(Subscription)

本文介绍 Apache RocketMQ 中订阅关系(Subscription)的定义、模型关系、内部属性及使用建议。

定义

订阅关系是 Apache RocketMQ 系统中消费者获取消息、处理消息的规则和状态配置。

订阅关系由消费者分组动态注册到服务端系统,并在后续的消息传输中按照订阅关系定义的过滤规则进行消息匹配和消费进度维护。

通过配置订阅关系,可控制如下传输行为:

  • 消息过滤规则:用于控制消费者在消费消息时,选择主题内的哪些消息进行消费,设置消费过滤规则可以高效地过滤消费者需要的消息集合,灵活根据不同的业务场景设置不同的消息接收范围。具体信息,请参见消息过滤。
  • 消费状态:Apache RocketMQ 服务端默认提供订阅关系持久化的能力,即消费者分组在服务端注册订阅关系后,当消费者离线并再次上线后,可以获取离线前的消费进度并继续消费。

订阅关系判断原则

Apache RocketMQ 的订阅关系按照消费者分组和主题粒度设计,因此,一个订阅关系指的是指定某个消费者分组对于某个主题的订阅,判断原则如下:

  • 不同消费者分组对于同一个主题的订阅相互独立如下图所示,消费者分组Group A和消费者分组Group B分别以不同的订阅关系订阅了同一个主题Topic A,这两个订阅关系互相独立,可以各自定义,不受影响。

    关于RocketMQ_第9张图片

  • 同一个消费者分组对于不同主题的订阅也相互独立如下图所示,消费者分组Group A订阅了两个主题Topic A和Topic B,对于Group A中的消费者来说,订阅的Topic A为一个订阅关系,订阅的Topic B为另外一个订阅关系,且这两个订阅关系互相独立,可以各自定义,不受影响。

    关于RocketMQ_第10张图片

模型关系

在 Apache RocketMQ 的领域模型中,订阅关系的位置和流程如下:关于RocketMQ_第11张图片

  1. 消息由生产者初始化并发送到Apache RocketMQ 服务端。
  2. 消息按照到达Apache RocketMQ 服务端的顺序存储到主题的指定队列中。
  3. 消费者按照指定的订阅关系从Apache RocketMQ 服务端中获取消息并消费。

内部属性

过滤类型

  • 定义:消息过滤规则的类型。订阅关系中设置消息过滤规则后,系统将按照过滤规则匹配主题中的消息,只将符合条件的消息投递给消费者消费,实现消息的再次分类。
  • 取值:
    • TAG过滤:按照Tag字符串进行全文过滤匹配。
    • SQL92过滤:按照SQL语法对消息属性进行过滤匹配。

过滤表达式

  • 定义:自定义的过滤规则表达式。
  • 取值:具体取值规范,请参见过滤表达式语法规范。

行为约束

订阅关系一致

Apache RocketMQ 是按照消费者分组粒度管理订阅关系,因此,同一消费者分组内的消费者在消费逻辑上必须保持一致,否则会出现消费冲突,导致部分消息消费异常。

  • 正确示例

    //Consumer c1Consumer c1 = ConsumerBuilder.build(groupA);c1.subscribe(topicA,"TagA");//Consumer c2Consumer c2 = ConsumerBuilder.build(groupA);c1.subscribe(topicA,"TagA");
    
  • 错误示例

    //Consumer c1Consumer c1 = ConsumerBuilder.build(groupA);c1.subscribe(topicA,"TagA");//Consumer c2Consumer c2 = ConsumerBuilder.build(groupA);c1.subscribe(topicA,"TagB");
    

使用建议

建议不要频繁修改订阅关系

在 Apache RocketMQ 领域模型中,订阅关系关联了过滤规则、消费进度等元数据和相关配置,同时系统需要保证消费者分组下的所有消费者的消费行为、消费逻辑、负载策略等一致,整体运算逻辑比较复杂。因此,不建议在生产环境中通过频繁修改订阅关系来实现业务逻辑的变更,这样可能会导致客户端一直处于负载均衡调整和变更的过程,从而影响消息接收。

三、集群模式

1.单Master模式

这种方式风险较大,一旦Broker重启或者宕机时,会导致整个服务不可用。不建议线上环境使用,可以用于本地测试。

2.多Master模式

一个集群无Slave,全是Master,例如2个Master或者3个Master,这种模式的优缺点如下:

优点:配置简单,单个Master宕机或重启维护对应用无影响,在磁盘配置为RAID10时,即使机器宕机不可恢复情况下,由于RAID10磁盘非常可靠,消息也不会丢(异步刷盘丢失少量消息,同步刷盘一条不丢),性能最高;

缺点:单台机器宕机期间,这台机器上未被消费的消息在机器恢复之前不可订阅,消息实时性会受到影响。

3.多Master多Slave模式-异步复制

每个Master配置一个Slave,有多对Master-Slave,HA采用异步复制方式,主备有短暂消息延迟(毫秒级),这种模式的优缺点如下:

优点:即使磁盘损坏,消息丢失的非常少,且消息实时性不会受影响,同时Master宕机后,消费者仍然可以从Slave消费,而且此过程对应用透明,不需要人工干预,性能同多Master模式几乎一样;

缺点:Master宕机,磁盘损坏情况下会丢失少量消息。

4.多Master多Slave模式-同步双写

每个Master配置一个Slave,有多对Master-Slave,HA采用同步双写方式,即只有主备都写成功,才向应用返回成功,这种模式的优缺点如下:

优点:数据与服务都无单点故障,Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高;

缺点:性能比异步复制模式略低(大约低10%左右),发送单个消息的RT会略高,且目前版本在主节点宕机后,备机不能自动切换为主机。

本篇文章介绍如何用两台服务器搭建双Nameserver、双主Broker、双从Broker、无单点故障的高可用RocketMQ集群,两台服务器IP分别为:192.168.31.186和192.168.31.23

你可能感兴趣的:(java-rocketmq,rocketmq,java)