RocketMQ的架构设计、关键特性与应⽤场景
1. ⾯试题分析
根据题⽬要求我们可以知道:
- RocketMQ的简介
- RocketMQ的演进
- RocketMQ的架构设计
- RocketMQ的关键特性
- RocketMQ的应⽤场景
分析需要全⾯并且有深度 容易被忽略的坑
- 分析⽚⾯
- 没有深⼊
2. RocketMQ的简介
RocketMQ⼀个纯java、分布式、队列模型的开源消息中间件,前身是MetaQ,是阿⾥研发的⼀个队列 模型的消息中间件,后开源给apache基⾦会成为了apache的顶级开源项⽬,具有⾼性能、⾼可靠、⾼ 实时、分布式特点。
3. RocketMQ的演进
RocketMQ⼀共前后经历了三代演进:
- 第⼀代,推模式 数据存储采⽤关系型数据库,典型代表包括Notify、Napoli。
- 第⼆代,拉模式 ⾃研的专有消息存储,在⽇志处理⽅⾯参考Kafka,典型代表MetaQ。
- 第三代,以拉模式为主,兼有推模式 低延迟消息引擎RocketMQ,在⼆代功能特性的基础上,为电商⾦融领域添加了可靠重试、基于⽂件存 储的分布式事务等特性。使⽤在了阿⾥⼤量的应⽤上,典型如双11场景,具有万亿级消息流转。
4. RocketMQ的架构设计
- RocketMQ的核⼼组件
RocketMQ主要由NameServer、Broker、Producer以及Consumer四部分构成。
1)NameServer:主要负责对于源数据的管理,包括了对于Topic和路由信息的管理。
NameServer是⼀个功能⻬全的服务器,其⻆⾊类似Dubbo中的Zookeeper,但NameServer与 Zookeeper相⽐更轻量。主要是因为每个NameServer节点互相之间是独⽴的,没有任何信息交互。
备注:下⾯的消息类型有Topic的介绍。
2)Producer 消息⽣产者,负责产⽣消息,⼀般由业务系统负责产⽣消息。
Producer由⽤户进⾏分布式部署,消息由Producer通过多种负载均衡模式发送到Broker集群,发 送低延时,⽀持快速失败。
3)Broker 消息中转⻆⾊,负责存储消息,转发消息。
Broker是具体提供业务的服务器,单个Broker节点与所有的NameServer节点保持⻓连接及⼼跳, 并会定时将Topic信息注册到NameServer,顺带⼀提底层的通信和连接都是基于Netty实现的。
Broker负责消息存储,以Topic为纬度⽀持轻量级的队列,单机可以⽀撑上万队列规模,⽀持消息 推拉模型。
官⽹上有数据显示:具有上亿级消息堆积能⼒,同时可严格保证消息的有序性。
4)Consumer 消息消费者,负责消费消息,⼀般是后台系统负责异步消费。
Consumer也由⽤户部署,⽀持PUSH和PULL两种消费模式,⽀持集群消费和⼴播消息,提供实时 的消息订阅机制。
5)⼤致流程
Broker在启动的时候会去向NameServer注册并且定时发送⼼跳,Producer在启动的时候会到 NameServer上去拉取Topic所属的Broker具体地址,然后向具体的Broker发送消息。具体如下图:
2. RocketMQ的消息领域模型
主要分为Message、Topic、Queue、Offset以及Group这⼏部分。
1)Topic
Topic表示消息的第⼀级类型,⽐如⼀个电商系统的消息可以分为:交易消息、物流消息等。⼀条消息必 须有⼀个Topic。 最细粒度的订阅单位,⼀个Group可以订阅多个Topic的消息。
2)Tag
Tag表示消息的第⼆级类型,⽐如交易消息⼜可以分为:交易创建消息,交易完成消息等。RocketMQ提 供2级消息分类,⽅便灵活控制。
3)Group
组,⼀个组可以订阅多个Topic。
4)Message Queue
消息的物理管理单位。⼀个Topic下可以有多个Queue,Queue的引⼊使得消息的存储可以分布式集群 化,具有了⽔平扩展能⼒。
在 RocketMQ 中,所有消息队列都是持久化,⻓度⽆限的数据结构,所谓⻓度⽆限是指队列中的每个存储 单元都是定⻓,访问其中的存储单元使⽤ Offset 来访问,offset 为 java long 类型,64 位,理论上在 100年内不会溢出,所以认为是⻓度⽆限。 也可以认为 Message Queue 是⼀个⻓度⽆限的数组,Offset 就是下标。
5. RocketMQ的关键特性
- 消息的顺序
消息的顺序指的是消息消费时,能按照发送的顺序来消费。例如:⼀个订单产⽣了 3 条消息,分别是订 单创建、订单付款、订单完成。消费时,要按照这个顺序消费才有意义。但同时订单之间⼜是可以并⾏ 消费的。
RocketMQ是通过将“相同ID的消息发送到同⼀个队列,⽽⼀个队列的消息只由⼀个消费者处理“来实现顺 序消息。如下图:
这样对于同⼀个订单的创建、付款和完成消息,确保按照这⼀顺序被发送和消费。
2. 消息重复
1)消息重复的原因
消息领域有⼀个对消息投递的QoS定义,分为:
- 最多⼀次(At most once)
- ⾄少⼀次(At least once)
- 仅⼀次( Exactly once)
QoS:Quality of Service,服务质量
⼏乎所有的MQ产品都声称⾃⼰做到了At least once。既然是⾄少⼀次,那避免不了消息重复,尤其是在分布式⽹络环境下。⽐如:⽹络原因闪断, ACK返回失败等等故障,确认信息没有传送到消息队列,导致消息队列不知道⾃⼰已经消费过该消息 了,再次将该消息分发给其他的消费者。
不同的消息队列发送的确认信息形式不同,例如RabbitMQ是发送⼀个ACK确认消息,RocketMQ是返回⼀ 个CONSUME_SUCCESS成功标志,kafka实际上有个offset的概念。
RocketMQ没有内置消息去重的解决⽅案,最新版本是否⽀持还需确认。
2)消息去重
1)去重原则:使⽤业务端逻辑保持幂等性
幂等性:就是⽤户对于同⼀操作发起的⼀次请求或者多次请求的结果是⼀致的,不会因为多次点击⽽产 ⽣了副作⽤,数据库的结果都是唯⼀的,不可变的。
只要保持幂等性,不管来多少条重复消息,最后处理的结果都⼀样,需要业务端来实现。
2)去重策略:保证每条消息都有唯⼀编号(⽐如唯⼀流⽔号),且保证消息处理成功与去重表的⽇志同时 出现。
建⽴⼀个消息表,拿到这个消息做数据库的insert操作。给这个消息做⼀个唯⼀主键(primary key)或 者唯⼀约束,那么就算出现重复消费的情况,就会导致主键冲突,那么就不再处理这条消息。
6. RocketMQ的应⽤场景
- 削峰填⾕ ⽐如如秒杀等⼤型活动时会带来较⾼的流量脉冲,如果没做相应的保护,将导致系统超负荷甚⾄崩溃。 如果因限制太过导致请求⼤量失败⽽影响⽤户体验,可以利⽤MQ 超⾼性能的消息处理能⼒来解决。
- 异步解耦 通过上、下游业务系统的松耦合设计,⽐如:交易系统的下游⼦系统(如积分等)出现不可⽤甚⾄宕 机,都不会影响到核⼼交易系统的正常运转。
- 顺序消息 与FIFO原理类似,MQ提供的顺序消息即保证消息的先进先出,可以应⽤于交易系统中的订单创建、⽀ 付、退款等流程。
- 分布式事务消息 ⽐如阿⾥的交易系统、⽀付红包等场景需要确保数据的最终⼀致性,需要引⼊ MQ 的分布式事务,既实 现了系统之间的解耦,⼜可以保证最终的数据⼀致性。 将⼤事务拆分成⼩事务,减少系统间的交互,既⾼效⼜可靠。再利⽤MQ 的可靠传输与多副本技术确保 消息不丢,At-Least-Once 特性来最终确保数据的最终⼀致性。
7. 扩展内容
- 分布式消息Kafka的原理、基础架构、使⽤场景
- Kafka、RocketMQ、RabbitMQ的优劣势⽐较
- 详解RPC远程调⽤和消息队列MQ的区别