一览纵山小,原来RocketMQ是这样工作的!

你好,我是猿java。

提起分布式消息中间件,作为一名 Java程序员,很自然会想起阿里巴巴开源的RocketMQ,它是一款高性能、高吞吐量的消息队列系统,在大数据、微服务、事件驱动架构等领域大放异彩,因此,本文我们将从全貌上介绍 RocketMQ的核心组件及其各自的作用,帮助大家能从整理上掌握 RocketMQ的脉络。

RocketMQ 核心组件

首先,我们看一张 RocketMQ的内核原理鸟瞰图,它抽象了 RocketMQ的 4个核心组件 NameServer、Broker、Producer、Consumer以及组件间的交互逻辑,具体信息如下:

img.png

接下来,我们重点分析 4个核心组件以及它们之间是如何交互的。

NameServer

NameServer是 RocketMQ中的注册中心,负责维护 Broker集群的路由信息,为了高可用,NameServer可以集群部署,需要特别注意:NameServer相互之间不会通信,它们是一种Peer to Peer的对等关系,并且每个 NameServer都保存着所有 Broker的信息。

NameServer的核心功能包括路由注册、路由发现、路由更新等,具体描述如下:

当 Broker启动时会向所有的 NameServer注册自身的信息,比如 IP、端口、Topic、Queue等,NameServer会将这些信息存入本地数据表中。默认情况下,Broker每隔 30s会向 NameServer发送一次心跳包,NameServer接收到心跳包后更新 Broker状态,如果 NameServer在 120s内没有接收到心跳包,会认为 Broker异常,从而剔除该心跳异常的 Broker。

当存在 Producer和 Consumer时,它们默认会每隔 30s定时从 NameServer获取 Broker集群信息并更新本地缓存,然后对 Broker列表进行负载均衡,从而将消息发送给 Broker或者从 Broker获取消息。

Broker

Broker是 RocketMQ中的数据存储节点,负责接收、存储和转发消息。

Broker可以集群部署,每个集群下面可以有多个组(BrokerName一样),每个组还可以主从部署,BrokerId=0 代表主节点,BrokerId=1代表从节点。

Broker的主要职责包括消息接收、消息存储、消息转发、消息索引、负载均衡,具体描述如下:

当 Broker启动时会所有的 NameServer注册信息以及后期定时向 NameServer发送心跳包,当 Broker接收到 Producer发送的消息后,首先会将消息写入 CommitLog(Write ahead log,WAL),然后开启后台线程将 CommitLog上的数据索引写入 write queue,这样可以确保消息持久化到磁盘上。

另外,Broker 会根据消费者的消费模式(推模式或拉模式),主动推送消息或等待消费者拉取消息,为了提高消息的检索速度,Broker还会为消息创建索引,支持快速定位和检索消息。

Producer

Producer是 RocketMQ中的生产者,负责发送消息。

Producer 和 Broker 是通过 Topic这样一个虚拟的概念建立关系的,当创建 Topic后,其实已经建立了 Topic和 Broker的关系,而这个关系的桥梁就是 queue,在 Broker中,有 write queue 和 read queue两种类型。

Producer每隔 30s从 NameServer拉取所有的 Topic以及 Broker信息,当消息发送到 Topic之后,消息首先会被写入一个 CommitLog的日志文件中,然后有后台线程将消息在 CommitLog磁盘上的地址等索引信息写入 write queue。这样,一个 Topic的数据就可以存储在不同的 Broker上,真正达到了数据的分布式存储,即便有部分Broker异常,受影响的数据也局限在这些 Broker上。

Producer发送消息有 3种方式:同步发送、异步发送和单向发送 。

  • 同步发送:Producer 发送消息后需要等待 Broker的确认,这种方式保证消息可靠地发送到 Broker,适用于对消息可靠性要求较高的场景,比如金融领域。
  • 异步发送:Producer 发送消息后不等待 Broker的确认,而是通过回调函数处理发送结果,该方式可以提高系统的并发性和吞吐量,适用于日志收集,监控报警等场景。
  • 单向发送:Producer 仅发送消息,不关心发送结果,也不等待 Broker的确认。这种方式的性能最高,但无法保证消息一定被发送成功,适用于数据采集,实时统计等场景。

消息重试:在消息发送失败时,Producer 可以进行重试,确保消息最终被成功发送。

Consumer

Consumer是 RocketMQ中的消费者,负责消费和处理消息,通常是真实的业务系统,Consumer的整个工作流程描述如下:

当 Consumer启动后,会向 Broker订阅感兴趣的 Topic,当 Topic中的 read queue有消息时,Consumer会定时拉取,然后执行真实的业务逻辑。当 Consumer成功处理消息后,需要向 Broker发送确认信息,Broker收到确认信息标记该消息已消费,避免重复消费,另外,为了防止丢消息,Consumer一般不建议多线程处理。Consumer可以通过顺序消费和并行消费等方式去拉取信息,从而满足不同的业务需求。

因为一个 Topic可以对应不同 Broker上的 read queue,因此,一个 Consumer可以消费不同 Broker上的数据。

典型应用场景

RocketMQ的应用场景主要包含下面 4种:

异步通信

在分布式系统中,通过 RocketMQ实现异步通信可以显著提高系统的响应速度和并发能力。例如,电商系统中订单创建后,通过 RocketMQ将订单数据异步发送给库存系统进行处理,避免了同步调用带来的延迟。

日志收集

RocketMQ可以用于分布式系统的日志收集和分析。各个服务将日志数据发送到 RocketMQ,由专门的日志处理系统进行消费和分析,帮助运维人员监控系统状态和排查故障。

流处理

RocketMQ 结合流处理框架(如 Apache Flink、Apache Storm)可以实现实时数据流处理。例如,在金融领域,通过 RocketMQ收集实时交易数据,并进行实时风控分析。

事件驱动架构

在事件驱动架构中,RocketMQ 作为事件总线,可以实现不同服务之间的解耦。例如,用户注册后发送欢迎邮件、用户订单支付成功后更新用户积分等业务逻辑,都可以通过 RocketMQ进行事件通知和处理。

总结

RocketMQ作为一款高性能的分布式消息中间件,在分布式系统中有其重要的一席之地,本文通过 RocketMQ内核鸟瞰图,对其重要的 4个组件以及组件间的交互进行了分析,通过上述内核鸟瞰图,我们能很好的把控 RocketMQ的整理脉络。

其实,我们在学习很多框架时,都是需要先从整体上掌握其框架脉络,而不是一开始就扎进细节里,这样很容易陷入其中出不来,最后导致放弃。

学习交流

如果你觉得文章有帮助,请帮忙转发给更多的好友,或关注公众号:猿java,持续输出硬核文章。

drawing