RocketMQ初识-博采众长,后来居上

155 阅读9分钟

引言

相信各位同学们无论是在日常工作或面试中,离不开对消息传递中间件的讨论;然而,目前市面上各种MQ产品百花齐放,我们如何基于自身的业务场景去选择最合适的来使用呢?

接下来的一系列文章,小宾将为大家带来对市面上常见的MQ中间件的学习分享,以及其在工程实践中的适用业务场景,感兴趣的同学可以持续关注我的专栏: MQ中间件

介绍概述

RocketMQ作为近年来最火的消息中间件之一,相信大部分同学们都对其有所了解;RocketMQ是由阿里推出的一款消息传递服务,其在创建之初的目的就是为了解决ActiveMQ的在其交易场景下的性能瓶颈问题;阿里的商城贸易业务的流量是非常巨大的,特别是在一些特殊时间,例如双十一,其流量会迎来极高的峰值

阿里的工程师们最初先调研了使用kafka进行替代,kafka的设计理念就是为了极高的吞吐性能,其partition分区的实现也能支持提升并发消费的能力;但是,kafka的高吞吐是一把双刃剑,极致的吞吐性能是靠舍弃了部分可靠性所换取的,而这在阿里贸易场景下是不可接受的,其每一个消息都可能涉及资金的计算,他们需要更高的可靠性保证

基于此种背景,RocketMQ就应运而生了;正如文章标题所说,阿里工程师们借鉴了kafka的优秀实现思想,设计出了更符合金融场景的高性能、高可靠的RocketMQ;可以说,RocketMQ在消息传递的浪潮中,掀起了一股厚积薄发的后浪

领域模型

一个消息在RocketMQ中,会经历三个阶段,生产者发送消息到服务端,服务端存储消息在队列中,消费者根据订阅Topic push/pull获取消息,这就是其主要的生命周期 image.png 消息传输模型

消息中间件常见的消息传输模型主要分为 点对点模型 和 发布订阅模型,其一句话概括为 点对点模型中,一条消息只能被一个消费者获取;发布订阅模型中,一条消息可以被多个消费者获取

发布订阅模型支持了一对多的上下游关系,生产者产生消息后,可以被多个服务所处理

Topic

Topic在RocketMQ中的角色是消息的最大维度集合,通常来说一个业务场景配置一个Topic,进行业务标识隔离;Topic是一个逻辑概念,其实际是由多个队列queue所构成的,消息存储在队列中,可通过增加队列实现水平扩容

属性

  • Topic名称:Topic标识,集群内全局唯一,由用户自行定义
  • 队列:一个Topic至少包含一个或多个队列,队列是消息的实际承载结构;队列数量可由服务端自行分配或由用户创建Topic时指定
  • 消息类型:RocketMQ支持普通消息、顺序消息、事务消息和延迟消息,从5.0开始RocketMQ 一个Topic只支持同一种类型的消息;服务端会对生产者发送的消息类型进行校验,若和Topic设定的消息类型不一致,会给生产者返回错误,生产消息失败

基于此,在创建Topic时,需要从业务场景划分和消息类型两方面考虑;不同的业务场景,配置独立的Topic,不同的消息类型,配置独立的Topic

Message Queue

消息队列在RocketMQ中的角色是消息传输和存储的实际承载容器,是消息存储的最小单元;消息队列具备FIFO特性,队列维度中的消息是基于生产时间有序排列的,消息根据offset标识其在队列中的位置;同时,消息队列是流式结构,可支持根据位点offset进行批量消费、回溯消费等

RocketMQ中的queue类同于kafka中的分区partition,其流式的设计结构带来了更灵活的消费特性

属性

  • 读写权限:控制队列的读写权限操作,可枚举
    • 6:允许读写消息
    • 4:只读,只允许读取消息
    • 2:只写,只允许写入消息
    • 0:读写都禁止

在3.x和4.x版本中,队列名称由 Topic名称+brokerID+queueID共同组成;在5.x版本中,队列和节点解耦,由集群全局唯一的字符串组成

Message

消息在RocketMQ中的角色是数据的最小承载单元,其具有 不可更改持久化存储 的特性;不可更改是指,生产者将消息发出后,消息内数据在整个生命周期中都是无法被修改的,消费者通过只读视图读取数据;持久化存储是指,服务端会将消息持久化写入磁盘,作为容灾恢复的保障

属性

  • Topic名称:标识消息发送到的Topic
  • 消息类型:标识消息的类型,普通/顺序/事务/延迟
  • 队列:发送到的队列,由服务端分配指定
  • 位点offset:消息在队列中存储的位置,由服务端分配指定
  • 消息ID:集群内全局唯一,由生产者自行生产
  • 索引:可选项,可设置索引键,方便快速检索到消息
  • Tag:可选项,消息标签,可在消费端根据Tag过滤指定消息进行消费
  • 延迟时间:可选项,延迟消息的发送时间,由生产者指定
  • 消息的发送时间:消息生产时间,生产者本地时钟
  • 消息的保存时间:消息在服务端存储的时间,事务消息和延迟消息较为特殊,为消息在消费端可见的时间
  • 消费重试次数:当消费者消费失败后,服务端重新投递消息的最大次数

消息大小限制

普通和顺序消息,大小限制为4MB;事务和延迟消息,大小限制是64KB

Producer

生产者在RocketMQ中的定位是封装发送消息到服务端的实体,通常集成在业务系统中;生产者和Topic是多对多的关系,一个Producer可以发送消息到多个Topic,一个Topic也可以接收来自多个Producer的消息

属性

  • 客户端ID:生产者的标识,集群内全局唯一,由RocketMQ客户端SDK自行生成

  • 通信参数

    • 接入点信息:必须,连接的服务端集群地址,建议使用域名而非IP,方便容器漂移等操作
    • 认证信息:可选,仅在服务端开启身份识别认证时需要
    • 请求超时阈值:可选,客户端网络请求的超时阈值,未配置使用默认的3s
  • Topic列表:生产者需要发送消息到的Topic集合,事务消息必须设置,用于半事务消息的状态校验

  • 事务检查器:生产者检查本地事务逻辑执行状态,对半事务消息后续操作确认

  • 发送失败重试策略:发送消息失败时的重试策略

ConsumerGroup

消费者分组在RocketMQ中的角色是承载多个消费行为相同的消费者集合,具备负载均衡功能;其同Topic一样,是一个逻辑概念,其由一个或多个消费者实际构成

消费组统一定义组内消费者的消费行为,订阅关系、消息顺序/并发投递、消费失败重试策略

属性

  • 消费组名称:消费组标识,集群内全局唯一,由消费端自行创建
  • 消息投递顺序性:服务端向消费组投递消息类型,顺序和并发两种,默认为并发投递
  • 消费重试策略:消息消费失败后,系统的重试策略
    • 最大重试次数:超过最大重试次数仍未被消费成功,消息将被投递到死信队列或丢弃
    • 重试间隔:重新投递消息的时间间隔,避免大批量密集重试将消费端打挂
  • 订阅关系:消费者订阅的主题,消息Tag的过滤规则等

消费组要求组内的消费者保持以下的消费行为一致:

  1. 消息投递顺序
  2. 消费重试策略

Consumer

消费者在RocketMQ中的角色是接收并处理消息的实体,通常被集成在业务系统中;消费者必须绑定到一个消费组中,以获取组内统一配置的消费行为;消费者分为三种类型:PushConsumer、SimpleConsumer、PullConsumer

属性

  • 消费组名称:标识消费者归属的消费组
  • 客户端ID:客户端标识,集群内全局唯一,由RocketMQ SDK自动生成
  • 通信参数
    • 接入点信息:必须,连接的服务端集群地址,建议使用域名而非IP,方便容器漂移等操作
    • 认证信息:可选,仅在服务端开启身份识别认证时需要
    • 请求超时阈值:可选,客户端网络请求的超时阈值,未配置使用默认的3s
  • 预绑定订阅关系列表:指定消费者的订阅关系,可在消费者初始化阶段,根据预绑定订阅关系校验指定Topic的权限和合法性
  • 消费监听器:服务端将消息投递到消费者后,消费者调用消息消费逻辑的监听器

Subscription

订阅关系在RocketMQ中的角色是消费者获取消息、处理消息和状态的配置;订阅关系由消费组动态注册到服务端,通过订阅关系可以控制如下传输行为:

  • 消息过滤规则:消费者根据消息Tag进行过滤
  • 消费状态:记录消费者消费进度,可在消费者宕机之后恢复故障前消费状态

订阅关系 是 Topic和ConsumerGroup之间的 image.png

属性

  • 过滤类型:消息过滤规则的类型,Tag过滤&SQL过滤
  • 过滤表达式:自定义的过滤规则表达式