RocketMQ系列(一) 基本介绍
阅读原文时间:2023年08月29日阅读:4

1、MQ 作用

MQ 的应用场景主要包含以下 3 个方面:

1.1、异步与解耦

当我们下了一个订单之后,订单服务会进行 RPC 同步调用 支付服务、库存服务、物流服务等,那么服务之间就会有耦合性,耦合性越高的话,容错性就越低,比如我们的支付服务如果宕机了,就会导致我们整个交易的异常,从而影响用户的体验。

如果我们中间加入了消息中间件,不管是支付还是库存等服务,都是通过异步的方式进行调用的,如果其中一个服务宕机了,不会影响我们用户下单的使用。

本质上 MQ 第一步完成了异步 ,第二步完成了解耦 。那么系统的容错性就越高。

1.2、流量削峰

流量削峰也可以叫削峰填谷,比如一些互联网公司大促场景,双十一、店庆或者秒杀活动,都会使用到消息中间件。

如果在不使用消息中间件或者没有流量削峰,每秒是很高的并发,这个时候如果我们的系统,如果要将数据写入到我们的 MYSQL 中,受限于 MYSQL 本身服务的上限,最大我们只能每秒处理 200 请求,这个时候会有大量的消息进行堆积,从而导致系统的奔溃。

这个时候我们可以将用户的请求消息通过 MQ 进行写入,因为消息中间件本身是对数据量处理比较高的一个系统,所以对于每秒 1000 请求,消息中间件可以处理,然后系统作为消息中间件的一个消费者,以固定的速度从 MQ 中拉取 200 个消息,完成我们的业务操作,用时间换空间确保系统的稳定性。

1.3、数据分发

如果 A 服务进行开发的时候,需要同时对接 B、C、D、E 四个服务,传统的接口调用,中间有调用改动就需要修改代码,当增加了 D 服务,需要修改 A 服务的代码去调用 D 服务完成响应的业务逻辑,同理如果要移除已对接的 E 服务,同样需要修改 A 服务代码删除对 E 服务的接口调用。

而如果 A 服务用到 MQ 消息中间件,A 服务只需将消息发送给 MQ, 对于新增的 D 服务,只需要增加对 A 服务消息的监听,而需要移除的 E 服务,同样只需取消对 A 服务消息的监听即可。对于 A 服务而言,B、C、D、E 只是它消息的消费者,消费者的任何变动都不会影响到生产者。生产者不需要任何的代码改动,只需要将数据分发出去,MQ 负责将数据发送到监听的消费者,这便是数据分发。

2、各种 MQ 比较

下面是现在主流 MQ 的特性及适用场景的比较:

特性

ActiveMQ

RabbitMQ

RocketMQ

Kafka

单机吞吐量

万级,比RocketMQ和Kafka第一个级别

同ActiveMQ

10万级,支撑高吞吐

10万级,高吞吐,一般配合大数据类的系统进行实时数据计算、日志采集等场景

topic数量对吞吐量的影响

topic可以达到几百/几千级别,吞吐量会有较小幅度的下降,这是RocketMQ的一大优势,在同等机器下,可以支撑大量的topic

topic从几十到几百时,吞吐量会大幅度下降,在同等机器下,kafka尽量保证topic数量不要过多,如果要支撑大规模的topic,需要增加更多的机器资源

时效性

ms级

微秒级别,RabbitMQ的特性,延迟最低

ms级别

延迟在ms级别以内

可用性

高,基于主从架构实现高可用

同ActiveMQ

非常高,分布式架构

非常高,分布式一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用

消息可靠性

有较低的概率丢失数据

基本不丢

经过参数优化配置,可以做到0丢失

经过参数优化配置,可以做到0丢失

功能支持

MQ领域的功能机器完备

基于erlang开发,并发能力很强,性能极好,延时很低

MQ功能较为完善,基本分布式,扩展性好

功能较简单,主要支持简单的MQ功能,在大数据领域的实时计算以及日志采集被大规模使用

其他

Apache开发,起步早,没有经过高吞吐场景验证,社区不活跃

开源、稳定、社区活跃度高

阿里开源,交给Apache,社区活跃度低

Apache开发,开源、高吞吐量、社区活跃度高

3、RocketMQ 基本概念

NameServer

NameServer是一个简单的 Topic 路由注册中心,支持 Topic、Broker 的动态注册与发现。

主要包括两个功能:

  • Broker管理,NameServer 接受 Broker 集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查 Broker 是否还存活;
  • 路由信息管理,每个 NameServer 将保存关于 Broker 集群的整个路由信息和用于客户端查询的队列信息。Producer 和 Consumer 通过 NameServer 就可以知道整个 Broker 集群的路由信息,从而进行消息的投递和消费。

NameServer 通常会有多个实例部署,各实例间相互不进行信息通讯。Broker 是向每一台 NameServer 注册自己的路由信息,所以每一个 NameServer 实例上面都保存一份完整的路由信息。当某个 NameServer 因某种原因下线了,客户端仍然可以向其它 NameServer 获取路由信息。

NameServer 其角色类似 Dubbo 和 Zookeeper,主要负责 Broker 的动态注册与发现。为什么不使用Zookeeper?Rocketmq 主要是在分布式情况下使用追求性能,因为 Zookeeper 最求最终一致性,所以在性能上会有所折扣。

Broker

Broker 是消息存储中心,主要作用是接收来自 Producer 的消息并存储,Consumer 从这里取得消息。

在 Master-Slave 架构中,Broker 分为 Master 与 Slave。一个 Master 可以对应多个 Slave,但是一个 Slave 只能对应一个 Master。Master 与 Slave 的对应关系通过指定相同的 BrokerName,不同的 BrokerId 来定义,BrokerId 为 0 表示 Master,非 0 表示 Slave。Master 也可以部署多个。 Master 既可以写又可以读,Slave 不可以写只可以读。

Producer

Producer 也称为消息发布者(生产者),负责生产并发送消息至 Topic。生产者向 Broker 发送由业务应用程序系统生成的消息。RocketMQ 提供了发送:同步、异步和单向(one-way)的多种范例。

Consumer

Consumer 也称为消息订阅者(消费者),负责从 Topic 接收并消费消息。消费者从 Broker 那里拉取信息并将其输入应用程序。从 Master 拿到消息,执行完成后,会发送一个消息给 Broker 进行确认,这个就是 ACK 确认。

  • 支持以推(push),拉(pull)两种模式对消息进行消费。
  • 同时也支持集群方式和广播方式的消费。
  • 提供实时消息订阅机制,可以满足大多数用户的需求。

Group

Group 分为两个部分 生产者和消费者:

  • 生产者:表示发送同一类消息的 Producer,通常情况下发送逻辑是一致的。发送普通消息时,用于标识使用,没有特别的用处。主要用来作用于事务消息,当事务消息中某条消息一直处于等待状态并超时,Broker 会回查同一个Group下的其他 Producer,确定该消息是 commit 还是 rollback。
  • 消费者:消费者的分组就非常有意义了,消费者是标识一类Consumer 的集合名称,这类 Consumer 通常消费一类消息,且消费逻辑一致。同一个 Consumer Group 下的各个实例将共同消费 Topic 的消息,起到负载均衡的作用。消费进度以 Consumer Group 为粒度管理,不同 Consumer Group 之间消费进度彼此不受影响,即消息 A 被 Consumer Group1 消费过,也会再给 Consumer Group2 消费。

Topic

用来区分消息的种类,表示一类消息的逻辑名字,消息的逻辑管理单位,无论生产还是消费消息,都需要执Topic。

一个发送者可以发送消息给一个或者多个 Topic。

一个消息接受者可以订阅一个或多个 Topic 消息。

Message Queue

消息队列 简称 Queue ,消息物理管理单位。用来并行发送和接收消息,相当于是 Topic 的分区。

一个 Topic 会有若干个 Queue,消息的生产一般会比消息消费的速度要快,消息进行消费的时会有对应的业务逻辑进行处理,这个时候就会降低消息消费的速度。所有一般 Topic 会有若干 个Queue。主要用来解决生产很快,消费很慢。

如果同一个 Topic 创建在不同的 Broker,那么不同的 Broker 有不同的 Queue,将物理存储在不同的 Broker 节点之上,具有水平扩展的能力。无论是生产者还是消费者,实际的操作都是针对 Queue 级别。

Tag

RocketMQ 支持在发送时给 Topic 的消息设置 Tag,用于同一主题下区分不同类型的消息。

来自同一业务单元的消息,可以根据不同业务目的在同一主题下设置不同标签。比如有一个 Topic 消息为水果,那么水果可以有其他的标签 可以是 香蕉、西瓜、草莓等等,我们可以把对应的消息,打上对应的标签(Tag),这个就是方便我们在消费的时候做对应的筛选。

标签能够有效地保持代码的清晰度和连贯性,并优化 RocketMQ 提供的查询系统。消费者可以根据Tag实现对不同子主题的不同消费逻辑,实现更好的扩展性。

Offset

在 RocketMQ 中,有很多 Offset 的概念。一般我们只关心暴露到客户端的 Offset。不指定的话,一般指的是消费者消息的偏移量(Consumer Offset)

Message Queue 是无限长的数组。一条消息进来下标就会涨 1,而这个数组的下标就是 Offset。

Message Queue 中的 Max Offset 表示消息的最大 Offset,Consumer Offset 可以理解为标记 Consumer Group 在一条逻辑 Message Queue 上,即消费进度。

4、RocketMQ 工作流程

RocketMQ 主要有四大核心组成部分:NameServer、Broker、Producer 以及 Consumer 四部分。这些角色通常以集群的方式存在,RocketMQ 基于纯 Java 开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。

核心的工作流程如下:

通过这张图就可以很清楚的知道,RocketMQ 大致的工作流程:

  • Broker 启动的时候,会往每台 NameServer(因为 NameServer 之间不通信,所以每台都得注册)注册自己的信息,这些信息包括自己的 ip 和端口号,自己这台 Broker 有哪些 topic 等信息。
  • Producer 在启动之后会跟会 NameServer 建立连接,定期从 NameServer 中获取 Broker 的信息,当发送消息的时候,会根据消息需要发送到哪个 topic 去找对应的 Broker 地址,如果有的话,就向这台 Broker 发送请求;没有找到的话,就看根据是否允许自动创建 topic 来决定是否发送消息。
  • Broker 在接收到 Producer 的消息之后,会将消息存起来,持久化,如果有从节点的话,也会主动同步给从节点,实现数据的备份
  • Consumer 启动之后也会跟会 NameServer 建立连接,定期从 NameServer 中获取 Broker 和对应 topic 的信息,然后根据自己需要订阅的 topic 信息找到对应的 Broker 的地址,然后跟 Broker 建立连接,获取消息,进行消费

总结:文章首先通过流程图的形式介绍了 MQ 的几个重要作用,接着到各种 MQ 的比较,然后引出 RocketMQ 的主要组成部分,最后是核心流程的讲解。这里只是讲了 RocketMQ 的一些基本概念,没有触及 RocketMQ 的搭建及项目使用,这些留到下个篇章继续吧。

参考资料: