Rocket MQ消息中间件

开发 架构
Producer 向一些队列轮流发送消息,队列集合称为 Topic,Consumer 如果做广播消费,则一个 Consumer 实例消费这个 Topic 对应的所有队列,如果做集群消费,则多个 Consumer 实例平均消费这个 Topic 对应的队列集合。

Rocket MQ 背景

至 2010 年,随着阿里业务的快速发展,急需一款支持顺序消息,拥有海量消息堆积能力的消息 Meta Q 1.0 在 2011 年诞生。

到 2012 年, Meta Q 已经发展到了 Meta Q 3.0 ,并抽象出了通用的消息引擎 Rocket MQ。随后,将 Rocket MQ 进行了开源。

到 2016 年, Meta Q 在当年双十一承载了万亿级消息的流转,跨越了一个新的里程碑,同时 Rocket MQ 进入 Apache 孵化。

图片图片

Rocket MQ 是什么

  • 是一个队列模型的消息中间件,具有高性能、高可靠、高实时、分布式特点
  • Producer、Consumer、队列都可以分布式
  • Producer 向一些队列轮流发送消息,队列集合称为 Topic,Consumer 如果做广播消费,则一个 Consumer 实例消费这个 Topic 对应的所有队列,如果做集群消费,则多个 Consumer 实例平均消费这个 Topic 对应的队列集合
  • 能够保证严格的消息顺序
  • 提供丰富的消息拉取模式
  • 高效的订阅者水平扩展能力
  • 实时的消息订阅机制
  • 亿级消息堆积能力
  • 较少的依赖

Rocket MQ 术语

Topic:标识一类消息的逻辑名字,消息的逻辑管理单位。无论消息生产还是消费,都需要指定 Topic。

Tag:Rocket MQ 支持给在发送的时候给 Topic 打 Tag,同一个 Topic 的消息虽然逻辑管理是一样的。但是消费 Topic1 的时候,如果你订阅的时候指定的是 Tag A,那么 Tag B 的消息将不会投递。

Message Queue:简称 Q。一个 Topic 将有若干个 Q。若 Topic 同时创建在不通的 Broker,则不同的 Broker 上都有若干 Q,消息将物理地存储落在不同 Broker 结点上,具有水平扩展的能力。

Offset:可以认为一条逻辑的 Message Queue 是无限长的数组。一条消息进来下标就会涨 1,而这个数组的下标就是 Offset。

Max Offset:这个 Offset 实际上是最新消息的 Offset + 1,即:下一条消息的 Offset。

Min Offset:标识现存在的最小 Offset。而由于消息存储一段时间后,消费会被物理地从磁盘删除,Message Queue 的 Min Offset 也就对应增长。这意味着比 Min Offset 要小的那些消息已经不在 Broker 上了,无法被消费。

Consumer Offset:表示的是下次拉取的 Offset 位置。

Rocket MQ 模块

Name Server

存储当前集群所有 Brokers 信息、Topic 跟 Broker 的对应关系。

Broker

集群最核心模块,主要负责 Topic 消息存储、消费者的消费位点管理(消费进度)。只有 Master 才能进行写入操作,Slave 从 Master 中同步数据。

Producer

生产者。发送消息的客户端角色。发送消息的时候需要指定 Topic。Producer 完全无状态,可集群部署。

Consumer

消费者,通常有两种实现,分别为 Push Consumer 和 Pull Consumer,通常我们采用 Push 的方式为主, Pull 的为辅的来进行消息的消费。

集群部署架构

图片图片

集群工作流程

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

模块功能特性

Name Sever

  1. Name Sever 用于存储 Topic、Broker 关系信息,功能简单,稳定性高。多个 Name Sever 之间相互没有通信,单台 Name Sever 宕机不影响其他 Name Sever 与集群;即使整个 Name Sever 集群宕机,已经正常工作的 Producer,Consumer,Broker 仍然能正常工作,但新起的 Producer, Consumer,Broker 就无法工作。
  2. Name Sever 压力不会太大,平时主要开销是在维持心跳和提供 Topic-Broker 的关系数据。但有一点需要注意,Broker 向 Name Sever 发心跳时,会带上当前自己所负责的所有 Broker 信息,如果 Topic 个数太多(万级别),会导致一次心跳中,就 Topic 的数据就 几十M,网络情况差的话,网络传输失败,心跳失败,导致 Name Sever 误认为 Broker 心跳失败。

Broker

高并发读写服务
  1. 消息顺序写:所有 Topic 数据同时只会写一个文件,一个文件满 1G,再写新文件,真正的顺序写盘,使得发消息 TPS 大幅提高。
  2. 消息随机读:Rocket MQ 尽可能让读命中系统 Page Cache,因为操作系统访问 Page Cache 时,即使只访问 1K 的消息,系统也会提前预读出更多的数据,在下次读时就可能命中 Page Cache ,减少 IO 操作。
负载均衡与动态伸缩
  • Topic 维度:假如一个 Topic 的消息量特别大,但集群水位压力还是很低,就可以扩大该 Topic 的队列数,Topic 的队列数跟发送、消费速度成正比。
  • Broker 维度:如果集群水位很高了,需要扩容,直接加机器部署 Broker 就可以。Broker 起来后向 Name Sever 注册,Producer、Consumer 通过 Name Sever 发现新 Broker,立即跟该 Broker 直连,收发消息。
  1. 负载均衡:Broker 上存 Topic 信息,Topic 由多个队列组成,队列会平均分散在多个 Broker 上,而 Producer 的发送机制保证消息尽量平均分布到所有队列中,最终效果就是所有消息都平均落在每个 Broker 上。
  2. 动态伸缩能力(非顺序消息):Broker 的伸缩性体现在两个维度:Topic, Broker。

高可用&高可靠

  1. 高可用:集群部署时一般都为主备,备机实时从主机同步消息,如果其中一个主机宕机,备机提供消费服务,但不提供写服务。
  2. 高可靠:所有发往 Broker 的消息,有同步刷盘和异步刷盘机制;同步刷盘时,消息写入物理文件才会返回成功,异步刷盘时,只有机器宕机,才会产生消息丢失,Broker 挂掉可能会发生,但是机器宕机崩溃是很少发生的,除非突然断电。

Broker 与 Name Sever 的心跳机制

单个 Broker 跟所有 Name Sever 保持心跳请求,心跳间隔为30秒,心跳请求中包括当前 Broker 所有的 Topic 信息。Name Sever 会反查 Broker 的心跳信息,如果某个 Broker 在2分钟之内都没有心跳,则认为该 Broker 下线,调整 Topic 跟 Broker 的对应关系。但此时 Name Sever 不会主动通知 Producer、Consumer 有 Broker 宕机。

Broker 刷盘策略

刷盘策略:Rocket MQ 的所有消息都是持久化的,先写入系统 Page Cache,然后刷盘,可以保证内存不磁盘都有一份数据,访问时,直接从内存读取。

异步刷盘: 举例:现有 SAS 15000 转磁盘测试顺序写文件,速度可以达到 300M 每秒左右,而线上的网卡一般都为千兆网卡,速度最快可达 128M 每秒, 写磁盘速度明显快于数据网络入口速度,那么刷盘的迕度肯定可以跟上消息的写入速度。

同步刷盘:和异步的唯一区别是异步写完 Page Cache 直接返回,而同步是等待刷盘完成之后再返回。


图片图片

Producer

  1. Producer 启动时,也需要指定 Name Sever 的地址,从 Name Sever 集群中选一台建立长连接。如果该 Name Sever 宕机,会自动连其他 Name Sever 。直到有可用的 Name Sever 为止。
  2. 心跳检测和 Broker 类似。
  3. Producer 端,每个实例在发消息的时候,默认会轮询所有的 Message Queue 发送,以达到让消息平均落在不同的 Queue 上。而由于 Queue 可以散落在不同的 Broker,所以消息就发送到不同的 Broker 下。当然了,可以发送消息到指定的队列中。比如根据店家的编号 Hash 到不同的队列中,形成有序的消息。如果想自己实现发送的策略,可以实现 MessageQueueSelector 这个接口。

图片图片

Consumer

  1. 消费者启动时需要指定 Name Sever 地址,与其中一个 Name Sever 建立长连接。消费者每隔 30 秒从 Name Sever 获取所有 Topic 的最新队列情况,这意味着某个 Broker 如果宕机,客户端最多要 30 秒才能感知。连接建立后,从 Name Sever 中获取当前消费 Topic 所涉及的 Broker,直连 Broker。
  2. 和 Name Sever 的心跳检测和 Broker 类似。
  3. 消费者消费模式
  • 集群消费:一个 Consumer Group 中的各个 Consumer 实例分摊去消费消息,即一条消息只会投递到一个 Consumer Group 下面的一个实例。
  • 广播消费:消息将对一个 Consumer Group 下的各个 Consumer 实例都投递一遍。即即使这些 Consumer 属于同一个 Consumer Group,消息也会被 Consumer Group 中的每个 Consumer 都消费一次。
  1. 负载均衡:消费者端的负载均衡,就是集群消费模式下,同一个 ID 的所有消费者实例平均消费该 Topic 的所有队列。
  2. 拉取流程:Consumer 端每隔一段时间主动向 Broker 发送拉消息请求,Broker 在收到 Pull 请求后,如果有消息就立即返回数据,Consumer 端收到返回的消息后,再回调消费者设置的 Listener 方法。如果 Broker 在收到 Pull 请求时,消息队列里没有数据,Broker 端会阻塞请求直到有数据传递或超时才返回。

图片图片

持久化 Commit Log

虽然每个 Topic 下面有很多 Message Queue,但是 Message Queue 本身并不存储消息。真正的消息存储会写在 Commit Log 的文件,Message Queue 只是存储 Commit Log 中对应的位置信息,方便通过 Message Queue 找到对应存储在 Commit Log 的消息。不同的 Topic,Message Queue 都是写到相同的 Commit Log 文件,也就是说 Commit Log 完全的顺序写。

图片图片

什么时候清理物理消息文件

消息存储在 Commit Log 之后,的确是会被清理的,但是这个清理只会在以下任一条件成立才会批量删除消息文件(Commit Log):

  1. 消息文件过期(默认72小时),且到达清理时点(默认是凌晨4点),删除过期文件。
  2. 消息文件过期(默认72小时),且磁盘空间达到了水位线(默认75%),删除过期文件。
  3. 磁盘已经达到必须释放的上限(85%水位线)的时候,则开始批量清理文件(无论是否过期),直到空间充足。

注意:若磁盘空间达到危险水位线(默认90%),出于保护自身的目的,Broker 会拒绝写入服务。

参考文献

  • Rocket MQ 用户指南 v3.2.4
  • 阿里云社区

https://yq.aliyun.com/articles/69647?spm=5176.100240.searchblog.7.ZgGuDF

https://yq.aliyun.com/articles/66101?spm=5176.100240.searchblog.101.s7dvlU

https://yq.aliyun.com/articles/66110?spm=5176.100239.blogcont66101.23.kpzm2R

责任编辑:武晓燕 来源: 政采云技术
相关推荐

2023-10-24 07:50:18

消息中间件MQ

2022-07-26 00:00:00

MQ消息中间件

2016-09-12 18:01:05

IBM

2021-12-14 10:39:12

中间件ActiveMQRabbitMQ

2022-11-02 10:08:46

分布式高并发消息中间件

2015-08-11 11:16:36

淘宝中间件

2023-05-08 08:09:26

路由元信息谓词

2022-08-09 08:31:29

RocketMQ消息中间件

2022-07-25 06:46:24

MQ中间件消息中间件

2022-10-21 10:48:17

消息中间件互联网应用协议

2022-02-13 23:04:28

RedisRabbitMQKafka

2024-01-24 08:19:02

Stream应用场景注解

2022-12-15 17:13:22

MQRocketMQ架构

2019-07-19 07:56:13

消息队列消息代理消息中间件

2022-10-28 13:33:05

Push模式互联网高并发

2022-09-21 16:09:28

消息中间件

2023-10-16 12:25:48

2024-07-11 11:17:00

消息队列Java

2022-12-27 17:56:40

ack机制RocketMQ

2019-11-18 09:58:11

中间件投递模式
点赞
收藏

51CTO技术栈公众号