深入研究RocketMQ生产者发送消息的底层原理
前言
hello,小伙伴们,王子又来和大家研究RocketMQ的原理了,之前的文章RocketMQ生产部署架构如何设计中,我们已经简单的聊过了生产者是如何发送消息给Broker的。
我们简单回顾一下这个过程。
生产者首先声明一个Topic,然后为了把消息存到对应的Topic中,先从NameServer拉取注册信息获取到Topic存放在哪个Broker中,然后就可以访问对应的Broker发送消息了。
大体流程就是这样,那么这个过程中具体都发生了什么呢,王子今天就和大家深入的探讨一下这其中的奥秘。
什么是MessageQueue
要弄明白生产者发送消息的原理,先要理解什么是MessageQueue。
在生产者声明Topic的时候,是要指定一个关键的参数的,就是MessageQueue,就是指定了你的Topic里面包含几个MessageQueue。
那么这个MessageQueue是做什么用的呢?
直接翻译过来就是消息队列,那么就可以理解成一个Topic对应多个MessageQueue,然后把消息存放到Topic下的消息队列中。
其实Topic、MessageQueue、Broker之间是有关联的。
现在假设我们有一个Topic,指定了它有4个MessageQueue,那么这个Topic在分布式的Broker中是如何存储的呢?
前面的文章我们就聊过,Topic的数据是分布式存储在多个Broker中的,如下图:

那么Topic中的一部分数据是通过什么渠道存储在不同的Broker集群中的呢?
相信小伙伴们都猜到了,就是通过MessageQueue,本质上来讲就是一个数据分片的机制。
假设我们的Topic中有1万条数据,那么可能会平均分布到4个MessageQueue中分片存储(这里不是绝对的,可以根据消息写入的策略来定)。
那么这4个MessageQueue又是怎么存储在Broker上的呢?
很有可能就是每个Broker上存放两个MessageQueue。所以MessageQueue是RocketMQ中非常关键的数据分片机制,实现了Topic数据的分布式存储。
生产者发送消息存入哪个MessageQueue
接下来我们思考一下,生产者发送消息的时候是如何确定存入哪个MessageQueue呢?
我们之前说过,存放消息之前,首先会从NameServer中拉取元数据,在元数据中生产者可以知道Topic有几个MessageQueue,每个MessageQueue存放在哪个Broker集群上。
然后呢,既然生产者知道了这些信息,我们暂时就认为生产者会把消息均匀的发送给当前Topic下的所有MessageQueue中。
比如一共20条消息,4个MessageQueue,那么每个MessageQueue中就存放5条消息。
至于其他的存放策略,我们之后的文章再仔细探讨。
通过这样的方式,生产者发送消息的请求就可以分布在多台的Broker上,那假设我们的每台Broker都可以抗下10万并发,两个Broker就可以抗下20万的并发。
同时,因为我们的消息数据是分片式存储在多个MessageQueue中的,MessageQueue又分布在多个Broker集群中,这样就可以保证RocketMQ存储海量消息了。
如果Broker发生故障怎么办
对于Broker发生故障这一问题,我们之前的文章已经讲过了,小伙伴们可以回顾一下:Broker的主从架构是怎么实现的?
主要使用的是4.5版本后的Dledger自动化切换主从的集群,当MasterBroker挂掉后是可以自动实现Slave到Master的转变的。
那么这里为什么我们还要谈这个问题呢?
小伙伴们想一下,如果MasterBroker挂掉了,要实现主从切换这一过程是需要时间的。
那么在切换的过程中,如果我们的生产者仍然发送消息过来,并且定位到了这台挂掉的MasterBroker,不就无法正常的写入数据了吗。
如果我们还是按照之前说的平均分发消息到MessageQueue,那么就会导致一段时间内访问到故障Broker上时全部是失败的。
对于这个问题,我们可以在生产者中开启一个开关:sendLatencyFaultEnable=true
一旦开启这个开关,它有个自动容错机制。
比如访问Broker时发现Broker响应超时或返回错误,那么在之后的一段时间里,就不会再去访问这个Broker集群了。
这样的话,当Broker发生故障,一段时间内生产者就不会频繁的访问这个发生异常的Broker集群了,过段时间后再去访问。
可能这个时候我们的主从切换已经结束了,这样再次访问的时候就正常了。
总结
今天我们主要聊了聊什么是MessageQueue,MessageQueue在RocketMQ中扮演什么角色,生产者是如何写消息到MessageQueue的,Broker发生故障生产者是如何保证自动容错的。
相信小伙伴们应该会有一些收获,那我们下期的消息中间件系列再见。
往期文章推荐:

深入研究RocketMQ生产者发送消息的底层原理的更多相关文章
- 🏆【Alibaba中间件技术系列】「RocketMQ技术专题」系统服务底层原理以及高性能存储设计分析
设计背景 消息中间件的本身定义来考虑,应该尽量减少对于外部第三方中间件的依赖.一般来说依赖的外部系统越多,也会使得本身的设计越复杂,采用文件系统作为消息存储的方式. RocketMQ存储机制 消息中间 ...
- Kafka生产者发送消息的三种方式
Kafka是一种分布式的基于发布/订阅的消息系统,它的高吞吐量.灵活的offset是其它消息系统所没有的. Kafka发送消息主要有三种方式: 1.发送并忘记 2.同步发送 3.异步发送+回调函数 下 ...
- Rocketmq异步发送消息
package com.bfxy.rocketmq.quickstart; import java.util.List; import org.apache.rocketmq.client.excep ...
- kafka 生产者发送消息
KafkaProducer 创建一个 KafkaThread 来运行 Sender.run 方法. 1. 发送消息的入口在 KafkaProducer#doSend 中,但其实是把消息加入到 batc ...
- RocketMQ3.2.2生产者发送消息自动创建Topic队列数无法超过4个
问题现象 RocketMQ3.2.2版本,测试时尝试发送消息时自动创建Topic,设置了队列数量为8: producer.setDefaultTopicQueueNums(8); 同时设置broker ...
- Rocketmq同步发送消息
package com.bfxy.rocketmq.quickstart; import org.apache.rocketmq.client.exception.MQBrokerException; ...
- 深入研究RocketMQ消费者是如何获取消息的
前言 小伙伴们,国庆都过的开心吗?国庆后的第一个工作日是不是很多小伙伴还沉浸在假期的心情中,没有工作状态呢? 那王子今天和大家聊一聊RocketMQ的消费者是如何获取消息的,通过学习知识来找回状态吧. ...
- RocketMQ生产者消息篇
系列文章 RocketMQ入门篇 RocketMQ生产者流程篇 RocketMQ生产者消息篇 前言 上文RocketMQ生产者流程篇中详细介绍了生产者发送消息的流程,本文将重点介绍发送消息的通信模式以 ...
- RocketMQ的发送模式和消费模式
前言 小伙伴们大家好啊,王子又来和大家一起闲谈MQ技术了. 通过之前文章的学习,我们已经对RocketMQ的基本架构有了初步的了解,那今天王子就和大家一起来点实际的,用代码和大家一起看看RocketM ...
随机推荐
- linux命令查询网站
http://linux.51yip.com/ http://man.linuxde.net/ Linux命令查询手册Linux终端下 esc + . 可以获取上次文件名
- 第二篇Scrum冲刺博客--Interesting-Corps
第二篇Scrum冲刺博客 站立式会议 1.会议照片 2.队友完成情况 团队成员 昨日完成 今日计划 鲍鱼铭 主页页面和探测空间设计及布局实现 主页页面跳转社区功能及社区设计及布局实现 叶学涛 设计页面 ...
- 匹配对象方法:group() 与 groups()
当在处理正则表达式的时候,除了正则表达式对象之外,还有另一个对象类型:匹配对象,即是成功调用match()或者search()所返回的对象. 匹配对象有两个主要方法:group() 和 groups( ...
- phoenix PQS的kerberos相关配置
thin 客户端的实例代码 jdbc:phoenix:thin:url=<scheme>://<server-hostname>:<port>;authentica ...
- 系综的实现方式(nve、nvt、npt)
一.NVE系综 更新位置和速度,v和e恒定. 二.NVT系综 几种实现的方式: 如: fix 1 all nve #更新位置和速度,e和V保持不变.若只有这个命令,就只nve系综,如果和控温命令一起, ...
- Mac上如果看不到.git目录的解决方法
Mac OS X上,如果需要查看.git目录下的隐藏文件,操作很简单: 做法是:打开一个Terminal终端窗口,输入: defaults write com.apple.finder AppleSh ...
- php高效读取和写入
/** * 删除非空目录里面所有文件和子目录 * @param string $dir * @return boolean */ function fn_rmdir($dir) { //先删除目录下的 ...
- Android开发java程序员常用代码,将字符串以逗号分别取出字符串String
public class StringSplit { public static void main(String[] args) { String sourceStr = "1,2,3,4 ...
- Android开发之解决Error:(16) Error: "ssdk_baidutieba_client_inavailable" is not translated in "en" (Englis
由于添加ShareSDK文件,导致打包突然报错, 错误信息: Error:(16) Error: "baidutieba_client_inavailable" is not tr ...
- 【学习中】Unity<中级篇> Schedule
章节 内容 签到 Unity3D 实战技术第二版视频教程(中级篇) 1.游戏引擎发展史 2.Unity发展史 3.3D图形学与必要组件 5月19日 4.核心类_GameObject类 5月19日 5. ...