MQ系列1:消息中间件执行原理MQ系列2:消息中间件的技术选型MQ系列3:RocketMQ 架构分析MQ系列4:NameServer 原理解析MQ系列5:RocketMQ消息的发送模式
在之前的文章中,我们学习了RocketMQ的原理;RocketMQ中 命名服务 ServiceName 的运行流程;以及消息生产、发送的原理和模式 。这一篇,就让我们从消息消费的角度去进一步的学习 。
1 消息消费消息的消费主要是由如下几个核心能力组成的:
- 消费方式:Push(推) 或者 Pull(拉)
- 消费模式:广播模式和集群模式
- 消息消费反馈
- 流量控制(包括消费并发线程数设置)
- 消息的过滤(Tag, Key),过滤标签 TagA||TagB||TagC
- Push方式(MQPushConsumer),MQ Server主动向消费端推送;这种模式不考虑消费端是否有能力处理消费数据,实时性比较高,能够及时推送数据,适合大部分业务场景 。但同时存在一个问题,如果遇到峰值期,瞬间推送过多消息,会导致积压 , 甚至客户端雪崩 。
- Pull方式(MQPullConsumer),消费端在有需要时,主动从MQ Server拉取数据 。消费端比较灵活,可以根据自己的吞吐能力,消费的节奏,主动安排消息拉取 。适合消费和计算耗时比较大的消费场景 。缺点就是如何从代码层面精准地控制拉取的频率,过短对消费端有压力,并且有可能空拉照成资源拉菲;过长可能对消息及时性有影响,可以采用长轮询的方式进行处理 。
- Push模式与Pull模式的区别Push方式的做法是,Consumer封装了长轮询的操作 , 并注册MessageListener监听器,当MessageListener监听到有新的消息的时候,消费端便被唤醒,读取消息进行消费 。从用户角度上,订阅消息并消费感觉消息是推过来的 。Pull方式的做法是,消费端主动去拉取数据,获取相应的Topic的,遍历MessageQueue集合,取数,重新标记offset,再取数,直至消费完成 。
- 集群负载均衡消费模式(默认)集群模式是一个主题下的单条消息只允许被同一消费组内的一个消费者消费,消费完即完成 , 即P2P 。在集群模式下 , 消息队列负载的模式:一个MessageQueue集合同一个时间内只允许被同一消费组内的单个消费者消费一次(这种模式不允许重复消费,如付款 , 订单提交),单个Consumer可以消费多个遍历MessageQueue集合 。
- 广播消费模式广播模式指的是当前主题下的消费组所有消费者都可以消费并处理消息一次 , 达到广播的目的 。很多业务场景,比如航班延迟的消息通知,告知客户端缓存信息过期需要重新拉起等 。
消息消费以及进度反馈的主步骤如下:
- 消费线程池消费完数据之后,将消息消费进度缓存在内存中 。
- 定时调度任务 5s 一次将消息队里的消费 offset 提交至Broker 。
- Broker接受到消息之后,存储在内存中,如果有新的过来,可以更行,同样的每5s将offset持久化下来 。
- 消费客户端从Broker拉取消息时,同步将MessageQueue的消费偏移量提交到Broker 。
- RocketMQ以Consumer Group(消费者小组)和 Queue(队列)为标准对消费刻度进行管理的
- Consumer Offset标记消费组在消息队列(Queue)上的消费进度 。
- 消费成功后,消费进度暂时更新到本地缓存,调度任务会定时(默认5s)将进度同步到broker(需注意如果宕机,消费进度未提交则可能导致被重复消费),Broker最终将消费进度持久化到磁盘 。
- RocketMQ支持并发消费,所以是多个线程并行处理,每次记录消费进度的时候,把线程中最小的offset值作为消费进度值,这样避免了消息丢失,但有重复消费的风险,业务中需保证操作幂等性 。
- offset存储模式:集群模式,消息进度存储于Broker上;广播模式,消息消费进度在消费端即可 。

文章插图
1.4 消费端流量控制可以在DefaultMQPushConsumer 对象中配置各种属性来对消费流量进行控制: