RocketMQ 基础篇(上)MQ
内容概述
# RocketMQ 基础篇(上)
# [1] RocketMQ 入门基础
# [1.1] MQ的定义
其实并没有标准定义。一般认为,消息中间件属于分布式系统中一个子系统,关注于数据的发送和接收,利用高效可靠的异步消息传递机制对分布式系统中的其余各个子系统进行集成。
- 高效: 对于消息的处理处理速度快。
- 可靠: 一般消息中间件都会有消息持久化机制和其他的机制确保消息不丢失。
- 异步: 指发送完一个请求,不需要等待返回,随时可以再发送下一个请求,既不需要等待。
一句话总结,消息中间件不生产消息,只是消息的搬运工。 
# [1.2] 及为什么使用消息中间件?
# 应用解耦
系统的耦合性越高,容错性就越低。
以电商应用为例,用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障或者因为升级等原因暂时不可用,都会造成下单操作异常,
影响用户使用体验。
使用消息中间件,系统的耦合性就会提高了。
比如物流系统发生故障,需要几分钟才能来修复,在这段时间内,物流系统要处理的数据被缓存到消息队列中,用户的下单操作正常完成。
当物流系统恢复后,继续处理存放在消息队列中的订单消息即可,终端系统感知不到物流系统发生过几分钟故障。

# 削峰限流
应用系统如果遇到系统请求流量的瞬间猛增,有可能会将系统压垮。有了消息队列可以将大量请求缓存起来,分散到很长一段时间处理,
这样可以大大提到系统的稳定性和用户体验。
互联网公司的大促场景(双十一、店庆活动、秒杀活动)都会使用到MQ。 
# 数据分发
通过消息队列可以让数据在多个系统更加之间进行流通。数据的产生方不需要关心谁来使用数据,只需要将数据发送到消息队列,
数据使用方直接在消息队列中直接获取数据即可。
接口调用的弊端,无论是新增系统,还是移除系统,代码改造工作量都很大。
使用MQ 做数据分发好处,无论是新增系统,还是移除系统,代码改造工作量较小。
所以使用MQ 做数据的分发,可以提高团队开发的效率。 
# [1.3] RocketMQ 产品发展
# RocketMQ 版本发展
Metaq1.x 是RocketMQ 前身的第一个版本,本质上把Kafka 做了一次java 版本的重写(Kafka 是sacla)。
Meta2.x,主要是对存储部分进行了优化,因为kafka 的数据存储,它的paration 是一个全量的复制,在阿里、在淘宝的这种海量交易。
Kafka 这种机制的横向拓展是非常不好的。2012 年阿里同时把Meta2.0 从阿里内部开源出来,取名RocketMQ,同时为了命名上的规范(版本上延续),
所以这个就 是RocketMQ3.0。
现在RocketMQ 主要维护的是4.x 的版本,也是大家使用得最多的版本,2017 年从Apache 顶级项目毕业。
# 阿里内部项目的使用
其实,在阿里公司内部,原则上遵守开源共建原则。RocketMQ 项目只维护核心功能,且去除了所有其他运行时依赖,核心功能最简化。
每个BU( Business Unit 业务单元)的个性化需求都在RocketMQ 项目之上进行深度定制。RocketMQ 向其他BU 提供的仅仅是Jar 包,
例如要定制一个Broker,那么只需要依赖rocketmq-broker 这jar 包即可,可通过API 进行交互,
如果定制client,则依赖rocketmq-client 这个jar 包,对其提供的api 进行再封装。
在RocketMQ 项目基础上几个常用的项目如下:
- com.taobao.metaq v3.0 = RocketMQ + 淘宝个性化需求
为淘宝应用提供消息服务 - com.alipay.zpullmsg v1.0 = RocketMQ + 支付宝个性化需求
为支付宝应用提供消息服务 - com.alibaba.commonmq v1.0 = Notify + RocketMQ + B2B 个性化需求
为B2B 应用提供消息服务
# 展望未来
从阿里负责RocketMQ 的架构核心人员的信息来看,阿里内部一直全力拓展RocketMQ。
2017 年10 月份,OpenMessaging 项目由阿里巴巴发起,与雅虎、滴滴出行、Streamlio 公司共同参与创立,
项目意在创立厂商无关、平台无关的分布式消息及流处理领域的应用开发标准。同时OpenMessaging 入驻Linux 基金会。
OpenMessaging 项目已经开始在Apache RocketMQ 中率先落地,并推广至整个阿里云平台。
另外RocketMQ5 的版本也在内部推进,主要的方向是Cloud Native(云原生)。
另外还要讲一下Apache RocketMQ 的商业版本,Aliware MQ 在微服务、流计算、IoT、异步解耦、数据同步等场景有非常广泛的运用。

# [2] RocketMQ 的物理架构
消息队列RocketMQ 是阿里巴巴集团基于高可用分布式集群技术,自主研发的云正式商用的专业消息中间件,既可为分布式应用系统提供异步解耦和削峰填谷的能力, 同时也具备互联网应用所需的海量消息堆积、高吞吐、可靠重试等特性,是阿里巴巴双11 使用的核心产品。 RocketMQ 的设计基于主题的发布与订阅模式,其核心功能包括消息发送、消息存储(Broker)、消息消费,整体设计追求简单与性能第一。
# [2.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 的核心,用于暂存和传输消息。
# [2.2] 物理架构中的整体运转
- NameServer 先启动
- Broker 启动时向NameServer 注册
- 生产者在发送某个主题的消息之前先从NamerServer 获取Broker 服务器地址列表(有可能是集群), 然后根据负载均衡算法从列表中选择一台Broker 进行消息发送。
- NameServer 与每台Broker 服务器保持长连接,并间隔30S 检测Broker 是否存活,如果检测到Broker 宕机(使用心跳机制,如果检测超过120S), 则从路由注册表中将其移除。
- 消费者在订阅某个主题的消息之前从NamerServer 获取Broker 服务器地址列表(有可能是集群),但是消费者选择从Broker 中订阅消息, 订阅规则由Broker 配置决定。
# [3] RocketMQ 的概念模型
# [3.1] 分组(Group)
生产者: 标识发送同一类消息的Producer,通常发送逻辑一致。发送普通消息的时候,仅标识使用,并无特别用处。**主要作用用于事务消息:
**
(事务消息中如果某条发送某条消息的producer-A 宕机,使得事务消息一直处于PREPARED 状态并超时,则broker
会回查同一个group 的其它producer,
确认这条消息应该commit 还是rollback)
消费者: 标识一类Consumer 的集合名称,这类Consumer 通常消费一类消息,且消费逻辑一致。
同一个Consumer Group 下的各个实例将共同消费topic 的消息,起到负载均衡的作用。
消费进度以Consumer Group 为粒度管理,不同Consumer Group 之间消费进度彼此不受影响,即消息A 被Consumer Group1
消费过,
也会再给Consumer Group2 消费。
# [3.2] 主题(Topic)
标识一类消息的逻辑名字,消息的逻辑管理单位。无论消息生产还是消费,都需要指定Topic。
区分消息的种类;一个发送者可以发送消息给一个或者多个Topic;一个消息的接收者可以订阅一个或者多个Topic 消息。
# [3.3] 标签(Tag)
RocketMQ 支持给在发送的时候给topic 打tag,同一个topic 的消息虽然逻辑管理是一样的。但是消费topic1 的时候,如果你消费订阅的时候指定的是tagA, 那么tagB 的消息将不会投递。
# [3.4] 消息队列(Message Queue)
消息队列简称Queue 或Q,消息物理管理单位。一个Topic 将有若干个Q。若一个Topic 创建在不同的Broker,则不同的broker 上都有若干Q,
消息将物理地存储落在不同Broker 结点上,具有水平扩展的能力。
无论生产者还是消费者,实际的生产和消费都是针对Q 级别。例如Producer 发送消息的时候,会预先选择(默认轮询)好该Topic
下面的某一条Q 发送;
Consumer 消费的时候也会负载均衡地分配若干个Q,只拉取对应Q 的消息。
每一条message queue 均对应一个文件,这个文件存储了实际消息的索引信息。并且即使文件被删除,
也能通过实际纯粹的消息文件(commit log) 恢复回来。
# [3.5] 偏移量(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 位置。