深入研究RocketMQ消费者是如何获取消息的
前言
小伙伴们,国庆都过的开心吗?国庆后的第一个工作日是不是很多小伙伴还沉浸在假期的心情中,没有工作状态呢?
那王子今天和大家聊一聊RocketMQ的消费者是如何获取消息的,通过学习知识来找回状态吧。
废话不多说,我们开始吧。
消费者组
首先我们了解一个概念,什么是消费者组。
消费者组你就可以把它理解为,给一组消费者起一个名字。
假设我们有一个订单Topic名字是OrderTopic,然后库存系统和积分系统都要消费这个Topic中的数据,我们分别给库存系统和积分系统起一个消费组名字:stock_consumer_group、integral_consumer_group。
设置消费者组名字是在代码中实现的,如下:
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("stock_consumer_group");
比如我们的库存系统提供了2台机器,每台机器上的消费者组名字都是stock_consumer_group,那么这2台机器就是一个消费者组。
大体结构如上图所示,那么当订单系统发送消息到OrderTopic中后,库存系统和积分系统是如何进行消费的呢?
默认情况下,这条消息发送到Broker后,库存系统和积分系统都会拉取这条消息,而且库存系统的两台机器中只有一台会消费到这条消息,积分系统也一样。
这就是消费组的概念,不同的系统设置不同的消费组,如果不同的消费组订阅了同一个Topic,那么对于Topic中的一条消息,每个消费组都会获取到这条消息。
集群模式和广播模式
接下来我们思考一个问题,对于消费者组而言,当它获取到一条消息后,假设消费者组内有多台机器,那么到底是只有一台机器获取到消息,还是所有机器都获取到消息呢?
这其实是消费的两种模式,集群模式和广播模式。
默认情况下我们都是使用的集群模式,也就是说消费者组收到消息后,只有其中的一台机器会接收到消息。
我们可以手动指定为广播模式。
consumer.setMessageModel(MessageModel.BROADCASTING)
指定为广播模式后,消费者组内的每台机器都会收到这条消息。
具体要根据业务场景选择消费模式。
MessageQueue与消费者的关系
接着我们想一下,对于一个Topic下的多个MessageQueue,消费者组中的多台机器是如何消费的呢?
这部分内容底层实现是很复杂的,我们可以简单的理解为它会均匀的将多个MessageQueue分配给消费者组中的多台机器消费。
举个例子,假如我们的OrderTopic有四个MessageQueue,这4个MessageQueue分布在两台MasterBroker上,每个MasterBroker上有两个MessageQueue。
然后库存系统作为一个消费者组有两台机器,那么最好的分配方式就是每台消费者机器负责两个MessageQueue,这样就实现了机器的负载消费,示意图如下:
所以我们可以大致的认为,一个Topic中的多个MessageQueue会被均匀的分布给一个消费者组中的多台机器进行消费,这里要注意一点,一个MessageQueue只能被一台消费者机器消费,但是一台消费者机器可以同时负责处理多个MessageQueue。
那么当消费者组中的机器数量发生变化时,是怎么处理的。
机器数量发生变化一般就两种情况,一种是有机器宕机了,另一种是增加机器进行集群扩容了。
其实这种情况下是会进行rebalance环节的,也就是会重新分配每个消费者机器要处理的MessageQueue。
Push模式和Pull模式
不知道小伙伴们还记不记得,在之前的文章RocketMQ的发送模式和消费模式中,我们已经用代码说明了消费者的两种消费模式:Push和Pull,当时只提供了Push消费的代码,而没有提供Pull消费的代码。
其实这两种模式本质上是一样的,都是消费者主动发出请求到Broker上拉取消息。
Push模式的底层也是通过消费者主动拉取的方式来实现的,只不过它的名字叫Push而已,意思是Broker尽可能实时的推送消息给消费者。
我们一般在使用RocketMQ的时候,消费模式基本都是使用的Push模式,因为Pull模式真的使用起来代码特别复杂,而且Push模式的底层还是Pull模式,只是对时效性有了更好的支持。
Push模式大体实现思路是这样的:当消费者发送请求到Broker拉取消息的时候,如果有新的消息可以消费,会立马返回消息到消费者进行消费,消费后会接着发送请求到Broker拉取消息。
也就说Push模式下,处理完一批消息后会理解再发送请求给Broker拉取下一批消息,所以时效性更好,看起来就像是Broker在实时推送消息。
当请求发送到Broker发现没有需要消费的消息时,就会让请求线程挂起,默认挂起15秒,然后会有另一个后台线程每隔一段时间判断一下是否有新消息需要消费,一旦发现了新的消息,就会去唤醒挂起的线程,将消息返回给消费者进行消费,然后消费完毕再次发送请求拉取消息。
这一部分的源码实现是很复杂的,我们只要了解它的核心思路就可以了。就算是Push模式,本质上也是对Pull模式的一种封装。
Broker如何读取消息返回给消费者
接下来我们来聊聊Broker是如何读取消息返回给消费者的。之前的文章深入研究Broker是如何持久化的中我们已经知道了Broker是如何持久化消息的,小伙伴们可以复习一下。
那么当消费者发送请求到Broker中拉取消息时,假设是第一次拉取,就会从MessageQueue中的第一条消息开始拉取。
如何定位到第一条消息的位置呢,首先Broker会找到MessageQueue对应的ConsumerQueue,从里面找到这条消息的offset,然后通过offset去CommitLog中读取消息数据,把消息返回给消费者。
当消费者消费完这条消息后,会提交一个消费的进度给Broker,Broker会记录下一个ConsumerOffset来标记我们的消费进度。
下次消费者再去这个MessageQueue中拉取消息时,就会从记录的消费位置继续拉取消息,而不用从头获取了。
总结
好了,到这里本篇文章就结束了。
今天主要和大家一起讨论了一下RocketMQ消费者的拉取和消费过程,也是国庆假期后的第一篇文章。
没有从国庆中收回心的小伙伴们(ps:王子也一样没有进入状态(`・ω・´))就与王子一起通过学习找回状态吧。
往期文章推荐:
深入研究RocketMQ消费者是如何获取消息的的更多相关文章
- JMS学习(八)-ActiveMQ Consumer 使用 push 还是 pull 获取消息
ActiveMQ是一个消息中间件,对于消费者而言有两种方式从消息中间件获取消息: ①Push方式:由消息中间件主动地将消息推送给消费者:②Pull方式:由消费者主动向消息中间件拉取消息.看一段官网对P ...
- rocketmq源码分析3-consumer消息获取
使用rocketmq的大体消息发送过程如下: 在前面已经分析过MQ的broker接收生产者客户端发过来的消息的过程,此文主要讲述订阅者获取消息的过程,或者说broker是怎样将消息传递给消费者客户端的 ...
- 深入研究RocketMQ生产者发送消息的底层原理
前言 hello,小伙伴们,王子又来和大家研究RocketMQ的原理了,之前的文章RocketMQ生产部署架构如何设计中,我们已经简单的聊过了生产者是如何发送消息给Broker的. 我们简单回顾一下这 ...
- RocketMQ消费者示例程序
转载请注明出处:http://www.cnblogs.com/xiaodf/ 本博客实现了一个简单的RocketMQ消费者的示例,MQ里存储的是经过Avro序列化的消息数据,程序读取数据并反序列化后, ...
- 转 Kafka、RabbitMQ、RocketMQ等消息中间件的对比 —— 消息发送性能和优势
Kafka.RabbitMQ.RocketMQ等消息中间件的对比 —— 消息发送性能和优势 引言 分布式系统中,我们广泛运用消息中间件进行系统间的数据交换,便于异步解耦.现在开源的消息中间件有很多,前 ...
- 基于Confluent.Kafka实现的KafkaConsumer消费者类和KafkaProducer消息生产者类型
一.引言 研究Kafka有一段时间了,略有心得,基于此自己就写了一个Kafka的消费者的类和Kafka消息生产者的类,进行了单元测试和生产环境的测试,还是挺可靠的. 二.源码 话不多说,直接上代码,代 ...
- RabbitMQ,RocketMQ,Kafka 几种消息队列的对比
常用的几款消息队列的对比 前言 RabbitMQ 优点 缺点 RocketMQ 优点 缺点 Kafka 优点 缺点 如何选择合适的消息队列 参考 常用的几款消息队列的对比 前言 消息队列的作用: 1. ...
- Rabbit mq订阅方式获取消息并可设置持久化
Rabbit 通过方式获取消息:订阅方式事实上是向queue注冊consumer,通过rpc向queue server发送注冊consumer的消息.rabbitMQ Server在收到消息后,依据消 ...
- RocketMQ 消费者
本文分析 DefaultMQPushConsumer,异步发送消息,多线程消费的情形. DefaultMQPushConsumerImpl MQClientInstance 一个客户端进程只有一个 M ...
随机推荐
- 长沙做假证u
长沙做假证[电/薇:187ヘ1184ヘ0909同号]办各类证件-办毕业证-办离婚证,办学位证书,办硕士毕业证,办理文凭学历,办资格证,办房产证不. 这是一个简单的取最大值程序,可以用于处理 i32 数 ...
- POJ-2299-Ultra-QuickSort(单点更新 + 区间查询+离散化)
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a seque ...
- Qt绘图学习(1)
paintEvent()被调用的时机;1.当窗口第一次被show()的时候,Qt程序会自动产生一个绘图事件,调用绘图事件:2.重新调整窗口部件大小的时候,系统也会产生一个绘制事件.3.当窗口部件被其他 ...
- 原生js实现jquery的siblings()
Element.prototype.siblings = function(callback){ var siblingElement = []; var parentAllElement = []; ...
- Linux:网络基础配置
一.修改主机名 hostname 查看主机名 1.hostname zy 修改主机名为zy,临时生效,重新登录系统生效. 2.想要永久修改,,需修改配置文件: vi /etc/sysconf ...
- [源码分析] OpenTracing之跟踪Redis
[源码分析] OpenTracing之跟踪Redis 目录 [源码分析] OpenTracing之跟踪Redis 0x00 摘要 0x01 总体逻辑 1.1 相关概念 1.2 埋点插件 1.3 总体逻 ...
- JS -- DOM(文档对象模型)
认识DOM(文档对象模型) DOM(Document Object Model):定义访问和处理HTML文档的标准方法. DOM 将HTML文档呈现为带有元素.属性和文本的树结构(节点树). < ...
- [LeetCode]198. 打家劫舍(DP)
题目 你是一个专业的小偷,计划偷窃沿街的房屋.每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警. 给定一个 ...
- Book of Shaders 02 - 矩阵:二维仿射变换练习
0x00 一些废话 如果要深入学习 CG (Computer Graphics,计算机图形学),必然要学习相关的数学知识.CG 涉及到多个不同的领域,根据所研究领域的不同,也会涉及到不同的数学分支.但 ...
- rabbitmq的安装&学习
主要按照 https://www.cnblogs.com/web424/p/6761153.html https://www.cnblogs.com/qiyebao/p/4822583.html 学习 ...