一、为什么要使用消息中间件(RocketMQ)
1.1 应用解耦
- 系统的耦合性越高,容错性就越低。以电商应用为例,用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障或者 因为升级等原因暂时不可用,都会造成下单操作异常,影响用户使用体验 。
- 使用消息中间件,系统的耦合性就会降低。比如物流系统发生故障,需要几分钟才能来修复,在这段时间内,物流系统要处理的数据被缓存到消息队 列中,用户的下单操作正常完成。当物流系统恢复后,继续处理存放在消息队列中的订单消息即可,终端系统感知不到物流系统发生过几分钟故障。
1.2流量削峰
应用系统如果遇到系统请求流量的瞬间猛增,有可能会将系统压垮。有了消息队列可以将大量请求缓存起来,分散到很长一段时间处理,这样可以大大提高系统的稳定性和用户体验。
1.3数据分发
通过消息队列可以让数据在多个系统更加之间进行流通。数据的产生方不需要关心谁来使用数据,只需要将数据发送到消息队列,数据使用方直接在消息队列中直接获取数据即可。 使用 MQ 做数据分发,无论是新增系统,还是移除系统,代码改造工作量较小。 所以使用 MQ 做数据的分发,可以提高团队开发的效率。
二、RocketMQ 产品发展(不重要)
2.1 RocketMQ 版本发展
- Metaq1.x :是 RocketMQ 前身的第一个版本,本质上把 Kafka 做了一次 java 版本的重写(
- Kafka 是 sacla)
- Meta2.x:主要是对存储部分进行了优化,因为 kafka 的数据存储,它的 paration 是一个全量的复制,在阿里、在淘宝的这种海量交易Kafka 这种 机制的横向拓展是非常不好的
- RocketMQ3.0:2012 年阿里同时把 Meta2.0 从阿里内部开源出来,取名 RocketMQ,同时为了命名上的规范(版本上延续),所以这个就 是。
- 现在 RocketMQ 主要维护的是 4.x 的版本,也是大家使用得最多的版本,2017 年从 Apache 顶级项目毕业
这篇文章写于2021年第四季度
2.2 阿里内部项目的使用
在阿里公司内部,RocketMQ 遵守开源共建原则。RocketMQ 项目只维护核心功能,每个业务单元的个性化需求都在 RocketMQ 项目之上进行深度定制。
2.3 展望未来
- 阿里内部一直全力拓展 RocketMQ。
- 2017 年 10 月份,OpenMessaging 项目由阿里巴巴发起,与雅虎、滴滴出行、Streamlio 公司共同参与创立, 项目意在创立厂商无关、平台无关的分布 式消息及流处理领域的应用开发标准。同时 OpenMessaging 入驻 Linux 基金会 。OpenMessaging 项目已经开始在 Apache RocketMQ 中率先落地,并推广至整个阿里云平台。
- RocketMQ5 的版本也在内部推进,主要的方向是 Cloud Native(云原生)
三、RocketMQ 的物理架构
RocketMQ 的设计基于主题的发布与订阅模式,其核心功能包括消息发送、消息存储(Broker)、消息消费,整体设计追求简单与性能第一。
3.1 核心概念
NameServer
-
NameServer 是整个 RocketMQ 的“大脑”,它是 RocketMQ 的服务注册中心,所以 RocketMQ 需要先启动 NameServer 再启动 Rocket 中的 Broker。Broker 在启动时向所有 NameServer 注册(主要是服务器地址等),生产者在发送消息之前先从 NameServer 获取 Broker 服务器地址列表(消费者和生产者一样),然后根据负载均衡算法从列表中选择一台服务器进行消息发送。 -
NameServer 与每台 Broker 服务保持长连接,并间隔 30S 检查 Broker 是否存活,如果检测到 Broker 宕机,则从路由注册表中将其移除。这样就可以实 -
现 RocketMQ 的高可用。具体细节后续的章节会进行总结。
生产者[Producer]
也称为消息发布者,负责生产并发送消息至 RocketMQ。
消费者[Consumer]
也称为消息订阅者,负责从 RocketMQ 接收并消费消息。
消息[Message]
生产或消费的数据,对于 RocketMQ 来说,消息就是字节数组。
主机[Broker]
RocketMQ 的核心,用于暂存和传输消息。
注意:生产者集群、消费者集群属于业务服务,不属于RocketMQ核心
3.2 物理架构中的整体运转流程
- NameServer 先启动
- Broker 启动时向 NameServer 注册
- 生产者在发送某个主题的消息之前先从 NamerServer 获取 Broker 服务器地址列表(有可能是集群),然后根据负载均衡算法从列表中选择一台 Broker 进行消息发送。
- NameServer 与每台 Broker 服务器保持长连接,并间隔 30S 检测 Broker 是否存活,如果检测到 Broker 宕机(使用心跳机制,如果检测超过120S),则从路由注册表中将其移除。
- 消费者订阅某个主题的消息进行消费
四、RocketMQ 的概念模型
4.1 核心概念
主题[Topic]
-
标识一类消息的逻辑名字,消息的逻辑管理单位。无论消息生产还是消费,都需要指定Topic。 -
RocketMQ 支持给在发送的时候给 Topic 加 Tag,同一个 Topic 的消息虽然逻辑管理是一样的。但是消费Topic的时候,如果你消费订阅的时候指定的是 TagA,那么 TagB 的消息将不会投递。 -
一个发送者可以发送消息给一个或者多个 Topic;一个消息的接收者可以订阅一个或者多个 Topic 消息标签[Tag] 。
分组[Group]
**生产者:**标识发送同一类消息的 Producer,通常发送逻辑一致。发送普通消息的时候,仅标识使用,并无特别用处。主要作用用于事务消息(看完后续的事物消息再来理解比较好): 事务消息中如果某条发送某条消息的producer-A宕机,使得事务消息一直处于PREPARED状态并超时,则broker会回查同一个group的其它Producer确认这条消息应该 commit 还是 rollback。
**消费者:**标识一类 Consumer 的集合名称,这类 Consumer 通常消费一类消息,且消费逻辑一致。同一个 Consumer Group 下的各个实例将共同消费 topic 的消息,起到负载均衡的作用。 消费进度以 Consumer Group 为粒度管理,不同 Consumer Group 之间消费进度彼此不受影响,即消息 A 被 Consumer Group1 消费过,也会再给 Consumer Group2 消费。
注意: 同一个Consumer Group组内的消费者(线程)不会重复消费,由Rocket 队列来记录消费偏移量(参考下文偏移量概念)
消息队列[Message Queue]
简称 Queue 或 Q。消息物理管理单位。一个 Topic 将有若干个 Q。若一个 Topic 创建在不同的 Broker,则不同的 Broker 上都有若干 Q,将消息物理地址存储落在不同 Broker 结点上,具有水平扩展的能力。
无论生产者还是消费者,实际的生产和消费都是针对 Q 级别。例如 Producer 发送消息的时候,会预先选择(默认轮询)好:该 Topic 下面的某一条 Q 发送;Consumer 消费的时候也会负载均衡地分配若干个 Q,只拉取对应 Q 的消息。
每一条 message queue 均对应一个文件,这个文件存储了实际消息的索引信息。并且即使文件被删除,也能通过实际纯粹的消息文件(commit log)
恢复回来。
偏移量[Offset]
-
RocketMQ 中,有很多 offset 的概念。一般我们只关心暴露到客户端的 offset。不指定的话,就是指 Message Queue 下面的 offset。 -
Message queue 是无限长的数组。一条消息进来下标就会涨 1,而这个数组的下标就是 offset,Message queue 中的 max offset 表示消息的最大 offset -
Consumer offset 可以理解为标记 Consumer Group 在一条逻辑 Message Queue 上,消息消费到哪里即消费进度。但从源码上看,这个数值是消费过的 ,最新消费的消息是 offset+1,即实际上表示的是下次拉取的 offset 位置。玩转各种消息
|