RocketMQ

RocketMQ简介

阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改为RocketMQ,是阿里参照kafka设计思想使用java实现的一套mq。同时将阿里系内部多款mq产品(Notify、metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖,保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下mq的架构,目前主要多用于订单交易系统。

常见的消息中间件产品的比较

RocketMQ

RocketMQ架构

RocketMQ作为一款纯java、分布式、队列模型的开源消息中间件,

支持事务消息、顺序消息、批量消息、定时消息、消息回溯等。

RocketMQ
大致流程
Broker在启动的时候会去向NameServer注册并且定时发送心跳,Producer在启动的时候会到NameServer上去拉取Topic所属的Broker具体地址,然后向具体的Broker发送消息

为了消除单点故障,增加可靠性或增大吞吐量,可以在多台机器上部署多个nameserver和broker,并且为每个broker部署1个或多个slave

架构上每个部分的概念

NameServer

NameServer的作用是Broker的注册中心。

每个NameServer节点互相之间是独立的,没有任何信息交互,也就不存在任何的选主或者主从切换之类的问题,因此NameServer是很轻量级的。单个NameServer节点中存储了活跃的Broker列表(包括master和slave),这里活跃的定义是与NameServer保持有心跳。

Topic

Topic 与 Tag 都是业务上用来归类的标识,区分在于 Topic 是一级分类,而 Tag 可以理解为是二级分类

是生产者在发送消息和消费者在拉取消息的类别。Topic与生产者和消费者之间的关系非常松散。一个生产者可以发送不同类型Topic的消息。消费者组可以订阅一个或多个主题,只要该组的实例保持其订阅一致即可。

​ Topic翻译为话题。我们可以理解为第一级消息类型,比如一个电商系统的消息可以分为:交易消息、物流消息等,一条消息必须有一个Topic

Tag

标签,意思就是子主题,为用户提供了额外的灵活性。有了标签,方便RocketMQ提供的查询功能。

可以理解为第二级消息类型,交易创建消息,交易完成消息… 一条消息可以没有Tag

Queue

一个topic下,可以设置多个queue(消息队列),默认4个队列。当我们发送消息时,需要要指定该消息的topic。

RocketMQ会轮询该topic下的所有队列,将消息发送出去。

在 RocketMQ 中,所有消息队列都是持久化,长度无限的数据结构,所谓长度无限是指队列中的每个存储单元都是定长,访问其中的存储单元使用 Offset 来访问,offset 为 java long 类型,64 位,理论上在 100年内不会溢出,所以认为是长度无限。

也可以认为 Message Queue 是一个长度无限的数组,Offset 就是下标。

Broker

用来存放消息

Broker是具体提供业务的服务器,单个Broker节点与所有的NameServer节点保持长连接及心跳,定时(每隔30s)注册Topic信息到所有Name Server。Name Server定时(每隔10s)扫描所有存活broker的连接,如果Name Server超过2分钟没有收到心跳,则Name Server断开与Broker的连接。底层的通信和连接都是基于Netty实现的。

负载均衡:Broker上存Topic信息,Topic由多个队列组成,队列会平均分散在多个Broker上,会自动轮询当前所有可发送的broker ,尽量平均分布到所有队列中,最终效果就是所有消息都平均落在每个Broker上

高可用:Broker中分masterslave两种角色,每个master可以对应多个slave,但一个slave只能对应一个master,master和slave通过指定相同的Brokername组成,其中不同的BrokerId==0 是master,非0是slave。

高可靠并发读写服务:master和slave之间的同步方式分为同步双写和异步复制,异步复制方式master和slave之间虽然会存在少量的延迟,但性能较同步双写方式要高出10%左右。

Topic、Broker、queue

RocketMQ

Producer-生产消息

与nameserver的关系

单个Producer和一台NameServer节点(随机选择)保持长连接,定时查询topic配置信息,如果该NameServer挂掉,生产者会自动连接下一个NameServer,直到有可用连接为止,并能自动重连。与NameServer之间没有心跳。

与broker的关系

单个Producer和与其关联的所有broker保持长连接,并维持心跳。默认情况下消息发送采用轮询方式,会均匀发到对应Topic的所有queue中。

Consumer-消费消息

与nameserver的关系

单个Consumer和一台NameServer保持长连接,定时查询topic配置信息,如果该NameServer挂掉,消费者会自动连接下一个NameServer,直到有可用连接为止,并能自动重连。与NameServer之间没有心跳。

与broker的关系

单个Consumer和与其关联的所有broker保持长连接,并维持心跳,失去心跳后,则关闭连接,并向该消费者分组的所有消费者发出通知,分组内消费者重新分配队列继续消费。

groupName

RocketMQ中也有组的概念。代表具有相同角色的生产者组合或消费者组合,称为生产者组或消费者组。

作用是在集群HA的情况下,一个生产者down之后,本地事务回滚后,可以继续联系该组下的另外一个生产者实例,不至于导致业务走不下去。在消费者组中,可以实现消息消费的负载均衡和消息容错目标。

有了GroupName,在集群下,动态扩展容量很方便。只需要在新加的机器中,配置相同的GroupName。启动后,就立即能加入到所在的群组中,参与消息生产或消费。

消费模式

集群模式

在默认情况下,就是集群消费,此时消息发出去后将只有一个消费者能获取消息。

广播模式

广播消费,一条消息被多个Consumer消费。消息会发给Consume Group中的每一个消费者进行消费。

RocketMQ的应用场景

1. 削峰填谷 流量削峰

比如如秒杀等大型活动时会带来较高的流量脉冲,如果没做相应的保护,将导致系统超负荷甚至崩溃。如果因限制太过导致请求大量失败而影响用户体验,可以利用MQ 超高性能的消息处理能力来解决。

2. 异步解耦

通过上、下游业务系统的松耦合设计,比如:交易系统的下游子系统(如积分等)出现不可用甚至宕机,都不会影响到核心交易系统的正常运转。

3. 顺序消息

与FIFO原理类似,MQ提供的顺序消息即保证消息的先进先出,可以应用于交易系统中的订单创建、支付、退款等流程。

4. 分布式事务消息

比如阿里的交易系统、支付红包等场景需要确保数据的最终一致性,需要引入 MQ 的分布式事务,既实现了系统之间的解耦,又可以保证最终的数据一致性。

RocketMQ集群部署方式

单Mater模式

优点:配置简单,方便部署

缺点:风险较大,一旦Broker重启或者宕机,会导致整个服务不可用

多Master模式

一个集群无 Slave,全是 Master,例如 2 个 Master 或者 3 个 Master

优点:配置简单,单个Master宕机重启对应用没有影响。消息不会丢失

缺点:单台机器宕机期间,这台机器上没有被消费的消息在恢复之前不可订阅,消息实时性会受到影响。

多Master多Slave模式(异步)

每个Master配置一个Slave,采用异步复制方式,主备有短暂消息延迟

优点:因为Master 宕机后,消费者仍然可以从 Slave消费,此过程对应用透明。不需要人工干预。性能同多 Master 模式几乎一样。

缺点:Master宕机后,会丢失少量信息

多Master多Slave模式(同步)

每个Master配置一个Slave,采用同步双写方式,只有主和备都写成功,才返回成功

优点:数据与服务都无单点, Master宕机情况下,消息无延迟,服务可用性与数据可用性都非常高

缺点:性能比异步复制模式略低,大约低 10%左右,发送单个消息的 RT会略高。目前主宕机后,备机不能自动切换为主机,后续会支持自动切换功能
RocketMQ

同步与异步的区别:
- 同步数据安全性高,效率低。因为是只有主备机都存储好了才会通知消息提供者
- 异步数据安全性低.效率高。因为是主机收到消息后就会通知消息提供者,但是如果这个时候备机在做备份时候失败了,就会导致数据没有备份