1RocketMQ 介绍 · SpringCloud微服务实战 · 看云

导航

1. RocketMQ 简介

RocketMQ 中间件有很长的历史,从2007年的Notify到2010年的Napoli,2011年省级为MetaQ,到2012年开始做RocketMQ,RocketMQ 使用Java 语言开发,在2016年RocketMQ开源了出来,并且到现在也一zhi很火,目前已经是Apache的顶级项目,并且目前是唯一一款支持事务的消息中间件。
第一代Notify 主要使用的推模型,解决了事务消息
第二代的MeatQ主要使用了拉模型,解决了顺序消息和海量堆积的问题
RocketMQ 基于长轮询的拉取模式,兼容了一代、二代的优点
据了解,RocketMQ在每年的双十一当天,有万亿级的消息通过RocketMQ流转

2. RocketMQ 各部分介绍

56860e7cc53f4b77e07339e6e4a44d51_MD5.webp

RocketMQ 有四部分组成,Producer、Consumer、Broker、NameServer

  • NameServer:NameServer是一个非常简单的Topic路由注册中心,NameServer通常也是集群的方式部署,各实例间相互不进行信息通讯。Broker是向每一台NameServer注册自己的路由信息,所以每一个NameServer实例上面都保存一份完整的路由信息。当某个NameServer因某种原因下线了,Broker仍然可以向其它NameServer同步其路由信息,Producer,Consumer仍然可以动态感知Broker的路由的信息其角色类似Dubbo中的zookeeper,支持Broker的动态注册与发现。主要包括两个功能:

    • Broker管理,NameServer接受Broker集群的注册信息并且保存下来作为路由信息的基本数据。然后提供心跳检测机制,检查Broker是否还存活
    • 路由信息管理,每个NameServer将保存关于Broker集群的整个路由信息和用于客户端查询的队列信息。然后Producer和Conumser通过NameServer就可以知道整个Broker集群的路由信息,从而进行消息的投递和消费。
  • Broker: Broker主要负责消息的存储、投递和查询以及服务高可用保证。Broker部署相对复杂,Broker分为Master与Slave,一个Master可以对应多个Slave,但是一个Slave只能对应一个Master,Master与Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId 来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。每个Broker与NameServer集群中的所有节点建立长连接,定时注册Topic信息到所有NameServer。

  • Producer:消息发布的角色,支持分布式集群方式部署。

    • Producer通过MQ的负载均衡模块选择相应的Broker集群队列进行消息投递,投递的过程支持快速失败并且低延迟。
    • Producer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic 服务的Master建立长连接,且定时向Master发送心跳。Producer完全无状态,可集群部署。
    • Producer Group:一类 Producer 的集合名称,这类 Producer 通常发送一类消息,且消费逻辑一致。
  • Consumer:消息消费的角色,支持分布式集群方式部署。支持以push推,pull拉两种模式对消息进行消费。同时也支持集群方式和广播方式的消费,它提供实时消息订阅机制,可以满足大多数用户的需求。

    • Consumer既可以从Master订阅消息,也可以从Slave订阅消息,消费者在向Master拉取消息时,Master服务器会根据拉取偏移量与最大偏移量的距离(判断是否读老消息,产生读I/O),以及从服务器是否可读等因素建议下一次是从Master还是Slave拉取。
    • Consumer与NameServer集群中的其中一个节点(随机选择)建立长连接,定期从NameServer获取Topic路由信息,并向提供Topic服务的Master、Slave建立长连接,且定时向Master、Slave发送心跳。
    • Consumer Group:一类 Consumer 的集合名称,这类 Consumer 通常消费一类消息,且消费逻辑一致。

3. 执行流程

  • 启动NameServer,NameServer起来后监听端口,等待Broker、Producer、Consumer连上来,相当于一个路由控制中心。
  • Broker启动,跟所有的NameServer保持长连接,定时发送心跳包。心跳包中包含当前Broker信息(IP+端口等)以及存储所有Topic信息。注册成功后,NameServer集群中就有Topic跟Broker的映射关系。
  • 收发消息前,先创建Topic,创建Topic时需要指定该Topic要存储在哪些Broker上,也可以在发送消息时自动创建Topic。
  • Producer发送消息,启动时先跟NameServer集群中的其中一台建立长连接,并从NameServer中获取当前发送的Topic存在哪些Broker上,轮询从队列列表中选择一个队列,然后与队列所在的Broker建立长连接从而向Broker发消息。
  • Consumer跟Producer类似,跟其中一台NameServer建立长连接,获取当前订阅Topic存在哪些Broker上,然后直接跟Broker建立连接通道,开始消费消息。

了解了上面几种角色和执行流程之后,再谈一下Topic 和 Message Queue 这两个名词。一个分布式消息中间件部署好之后,可以给很多应用提供服务,同一应用也有不同类型的消息要发送,这些不同类型的消息以不同的Topic名称来区分。所以发送消息前,需要先创建Topic
针对每个Topic发送和接收的消息,还需要解决性能的问题。如果一个Topic 需要发送和接收消息的数据量非常大,需要能支持增加并行处理的机器来提高处理速度,这时候一个Topic 可以根据需要设置多个Message Queue,Message Queue 类似分区或Partition 。Topic 有很多个Message Queue 之后,消息可以并行的向各个Message Queue 发送消息,消费者也可以并行的从多个Message Queue 读取消息并消费

4. 分布式事务

RocketMQ 4.3版本以后才支持分布式事务,RocketMQ的事务消息模型借鉴了2PC模式,整个交互流程如下图所示:
eff5927c7ca11e0c31a93ca8375bf7ea_MD5.png
图来自于http://rocketmq.apache.org/rocketmq/the-design-of-transactional-message

  1. 事务发起方首先发送一条半消息到MQ
  2. MQ通知事务发起方,表示成功收到了这条半消息
  3. 事务发起方执行本地事务
  4. 根据本地事务执行结果向MQ反馈结果是commit或者是rollback,如果消息是rollback,MQ将删除该半消息不进行下发,如果是commit消息,MQ将会把这个消息发送给consumer端
  5. 如果第4步没有成功反馈,MQ会发送状态回查确认
  6. 事务发起方检查本地事务状态
  7. 将第6步结果反馈给MQ