思维导图
1.概述
1.1 为什么要用RocketMQ?
1.1.1 应用解耦
(1)系统的耦合性越高,容错性就越低。
以电商为例,用户创建完订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个系统出现故障或者因为升级等原因暂时不可用,都会造成下单的异常,影响用户的体验。
(2) 如下图:
- 子系统间耦合性太大的问题,使用mq之后,我们只需要依赖于mq,避免了各个子系统间的强依赖问题。
- 订单系统作为消息生产者,保证它自己没有异常即可,不会受到支付系统等业务子系统的异常影响,并且各个消费者业务子系统之间,也互不影响。
- 这样就把之前复杂的业务子系统的依赖关系,转换为只依赖于mq的简单依赖,从而显著的降低了系统间的耦合度。
1.1.2 流量削峰
(1)应用系统如果遇到系统请求流量瞬间猛增,有可能会将系统压垮。
如果有消息队列,遇到此情况,可以将大量请求存储起来,将一瞬间的峰值请求分散到一段时间进行处理,这样可以大大提高系统的稳定性
(2) 如下图:
- 由于突然出现的请求峰值,导致系统不稳定的问题。使用mq后,能够起到消峰的作用。
- 订单系统接收到用户请求之后,将请求直接发送到mq,然后订单消费者从mq中消费消息,做写库操作。
- 如果出现请求峰值的情况,由于消费者的消费能力有限,会按照自己的节奏来消费消息,多的请求不处理,保留在mq的队列中,不会对系统的稳定性造成影响
1.1.3 异步
(1)用户调用一个接口的时候,可能该接口调用了别的方法。
例如:用户注册的时候,后台可能需要调用:查询数据库,插入数据库,发送邮件等等…
(2)但是用户可能并不需要后台将所有的任务执行完毕.
那么此时在初入数据口后面加入MQ,用户就能很快得到注册成功的响应而去做一些别的事情。
mq的机制又能保证最终的一致性,所以使用起来很安全很稳定。
(3)如下图:
- 同步接口调用导致响应时间长的问题,使用mq之后,将同步调用改成异步,能够显著减少系统响应时间。
- 系统A作为消息的生产者,在完成本职工作后,就能直接返回结果了。而无需等待消息消费者的返回,它们最终会独立完成所有的业务功能。
- 这样能避免总耗时比较长,从而影响用户的体验的问题。
1.2 RocketMQ 与其他异同
2.架构与组成
2.1 架构图
2.1.1 简单
如果不考虑负载均衡和高可用,最简单的Broker,Producer和Consumer之间的关系如下图所示:
2.1.2 架构集群图
2.2 消息模型(Message Model)
(1)图
(2)组成
- 主要由 Producer、Broker、Consumer 三部分组成。
其中Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。 - Broker 在实际部署过程中对应一台服务器,每个 Broker 可以存储多个Topic的消息,每个Topic的消息
也可以分片存储于不同的 Broker。 - Message Queue 用于存储消息的物理地址,每个Topic中的消息地址存储于多个 Message Queue 中。
- ConsumerGroup 由多个Consumer 实例构成。
2.3 Producer 与 Producer Group
2.3.1 Producer(生产者)
(1)表示消息队列的生产者,用来生产和发送消息的,一般指业务系统。
(2)与 Name Server 集群中的其中一个节点(随机)建立长链接(Keep-alive),定期从 Name Server 读取 Topic 路由信息,
(3)并向提供 Topic 服务的 Master Broker 建立长链接,且定时向 Master Broker 发送心跳。
(4)RocketMQ提供了发送:普通消息(同步、异步和单向(one-way)消息)、定时消息、延时消息、事务消息。
2.3.2 Producer Group(生产者集群)
(1) 是一类Producer的集合名称。
(2)这类Producer通常发送一类消息,且发送逻辑一致。相同角色的生产者被分组在一起
(3)同一生产者组的另一个生产者实例可能被broker联系,以提交或回滚事务,以防原始生产者在交易后崩溃。
(4) 每个生产者组只允许一个实例,以避免对生产者实例进行不必要的初始化。
2.4 Name Server
2.4.1 概述
名称服务,充当路由消息的提供者。
(1)是一个几乎无状态节点,可集群部署,节点之间无任何信息同步。
(2)在消息队列 RocketMQ 中提供命名服务,更新和发现 Broker 服务。
(3)每个broker在启动的时候会到NameServer注册
2.4.2 2个功能
(1)接收broker的请求,注册broker的路由信息
(2)接收client(producer/consumer)的请求,根据某个topic获取其到broker的路由信息
2.5 Broker
2.5.1 概述
(1)消息中转角色,负责存储消息,转发消息。
可以理解为消息队列服务器,提供了消息的接收、存储、拉取和转发服务。
(2)broker是RocketMQ的核心,所以需要保证broker的高可用
(2)broker分为 Master Broker 和 Slave Broker
- 一个 Master Broker 可以对应多个 Slave Broker,但是一个 Slave Broker 只能对应一个 Master Broker。
- Master与Slave的对应关系通过指定相同的BrokerName,不同的BrokerId来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。
(4)每个Broker与Name Server集群中的所有节点建立长连接,定时注册Topic信息到所有Name Server。
- Broker 启动后需要完成一次将自己注册至 Name Server 的操作
- 随后每隔 30s 定期向 Name Server 上报 Topic 路由信息。
2.5.2 组成
2.5.2.1 Broker、topic、queue关系图
2.5.2.2 Topic及分片
(1)Topic
消息的第一级类型,比如一个电商系统的消息可以分为:交易消息、物流消息… 一条消息必须有一个Topic。
(2)Topic分片
RocketMQ的一个Topic可以分布在各个Broker上,我们可以把一个Topic分布在一个Broker上的子集定义为一个Topic分片。
2.5.2.3 Queue
将Topic分片再切分为若干等分,其中的一份就是一个Queue。
(1)概述
- Queue是Topic在一个Broker上的分片,在分片基础上再等分为若干份(可指定份数)后的其中一份,是负载均衡过程中资源分配的基本单元。
- 一个topic下,我们可以设置多个queue(消息队列)。当我们发送消息时,需要要指定该消息的topic。RocketMQ会轮询该topic下的所有队列,将消息发送出去。
- 集群消费模式下一个消费者只消费该Topic中部分Queue中的消息,当一个消费者开启广播模式时则会消费该Topic下所有Queue中的消息。
(2)queue数量指定方式
每个Topic分片等分的Queue的数量可以不同,由用户在创建Topic时指定,方式如下:
- 代码指定
producer.setDefaultTopicQueueNums(8);
- 配置文件指定
同时设置broker服务器的配置文件broker.properties:defaultTopicQueueNums=16
- rocket-console控制台指定
2.5.2.4 Tags
- Topic下的次级消息类型/二级类型(注:Tags也支持TagA || TagB这样的表达式),可以在同一个Topic下基于Tags进行消息过滤。
- Tags的过滤需要经过两次比对,首先会在Broker端通过Tag hashcode进行一次比对过滤,匹配成功传到consumer端后再对具体Tags进行比对,以防止Tag hashcode重复的情况。
- 比如交易消息又可以分为:交易创建消息,交易完成消息等… 一条消息可以没有Tag。有了标签,来自同一个业务模块的不同目的的消息可能具有相同的主题和不同的标签。
- Queue中具体的存储单元结构如下图,最后面的8个Byte存储Tag信息.
2.6 Consumer 与 Consumer Group
2.6.1 Consumer(消费者)
(1)消息消费者,一般由业务后台系统异步的消费消息
(2)与 Name Server 集群中的其中一个节点(随机)建立长连接,定期从 Name Server 拉取 Topic 路由信息
(3)并向提供 Topic 服务的 Master Broker、Slave Broker 建立长连接,且定时向 Master Broker、Slave Broker 发送心跳。
(4)Consumer 既可以从 Master Broker 订阅消息,也可以从 Slave Broker 订阅消息,订阅规则由 Broker 配置决定。
(5)模式
- Push Consumer(对应推模式)。
Consumer 的一种,应用通常向 Consumer 对象注册一个 Listener 接口,一旦收到消息,Consumer 对象立刻回调 Listener 接口方法。 - Pull Consumer(对应拉模式)
Consumer 的另一种,应用通常主动调用 Consumer 的拉消息方法从 Broker 拉消息,主动权由应用控制。
2.6.2 Consumer Group
(1)是一类Consumer的集合名称。
(2)这类通常消费一类消息,且消费逻辑一致(使用相同 Group ID 的订阅者属于同一个集群。
同一个集群下的订阅者消费逻辑必须完全一致(包括 Tag 的使用),这些订阅者在逻辑上可以认为是一个消费节点)。
(3)消费者群体实现了负载平衡和容错的目标。