RocketMQ - 你的消息队列技术引路人
文章平均质量分 76
在这里,我们将拨开迷雾,直击核心,带你领略RocketMQ的无限魅力。深度解析RocketMQ的核心架构,实战演练高并发场景下的消息处理,开启属于你的技术飞跃之旅
无法无天过路客
Java程序员一枚,喜欢记录收集技术文章
展开
-
MySQL - Read Committed隔离级别是如何基于ReadView机制实现的?
这个时候事务A发起查询,发现当前这条数据的trx_id是70,也就是说数据ReadView的事务id范围之间,说明是他生成ReadView之前就有个活跃的事务,是这个事务修改了这条数据的值,但是此时这个事务B还没提交,所以ReadView的m_ids活跃事务列表里,是有[60,70]两个id的,所以此时根据ReadView的机制,此时事务A是无法查询到事务B修改的值B的。一个非常核心的要点在于,当你一个事务设置他处于RC隔离级别的时候,他是每次发起查询都重新生成一个ReadView。原创 2024-04-10 07:35:03 · 57 阅读 · 0 评论 -
RocketMQ - 如何对生产环境的RocketMQ集群进行消息轨迹的追踪?
然后消息被消费到Consumer端之后,它也会上报一些轨迹数据到内置的RMQ_SYS_TRACE_TOPIC里去,包括如下一些东西:Consumer的信息、投递消息的时间、这是第几轮投递消息、消息消费是否成功、消费这条消息的耗时。接着消息到Broker端之后,Broker端也会记录消息的轨迹数据,包括如下:消息存储的Topic、消息存储的位置、消息的key、消息的tags。在订阅消息的时候,对于Consumer也是同理的,在构造函数的第二个参数设置为true,就是开启了消费时候的轨迹追踪。原创 2024-03-13 08:04:55 · 76 阅读 · 0 评论 -
RocketMQ - 企业级的RocketMQ集群如何进行权限机制的控制?
要在RocketMQ中实现权限控制也不难,首先我们需要在broker端放一个额外的ACL权限控制配置文件,里面需要规定好权限,包括什么用户对哪些Topic有什么操作权限,这样的话,各个Broker才知道你每个用户的权限。如果一个公司有很多技术团队,每个技术团队都会使用RocketMQ集群中的部分Topic,那么此时可能就会有一个问题了,如果订单团队使用的Topic,被商品团队不小心写入了错误的脏数据,那怎么办呢?接着看看生产者和和消费者里,如何指定你的团队分配到的RocketMQ的账号。原创 2024-03-13 08:03:52 · 110 阅读 · 0 评论 -
RocketMQ - Consumer是如何从Broker上拉取一批消息过来处理的?
当你的请求发送到Broker,结果他发现没有新的消息给你处理的时候,就会让请求线程挂起,默认是挂起15秒,然后这个期间他会有后台线程每隔一会儿就去检查一下是否有的新的消息给你,另外如果在这个挂起过程中,如果有新的消息到达了会主动唤醒挂起的线程,然后把消息返回给你。当然其实消费者进行消息拉取的底层源码是非常复杂的,涉及到大量的细节,但是他的核心思路大致就是如此,我们只要知道,其实哪怕是用常见的Push模式消费,本质也是消费者不停的发送请求到broker去拉取一批一批的消息就行了。原创 2024-03-21 07:33:29 · 54 阅读 · 0 评论 -
RocketMQ - 一个消费组中的多个Consumer是如何均匀分配消息队列的?
此时重平衡组件一旦知道了消费组内有哪些Consumer之后,接着就好办了,无非就是把Topic下的MessageQueue均匀的分配给这些Consumer了,这个时候其实有几种算法可以进行分配,但是比较常用的一种算法就是简单的平均分配。总之,一切都是平均分配的,尽量保证每个Consumer的负载是差不多的。实际上,每个Consumer在启动之后,都会干一件事情,就是向所有的Broker进行注册,并且持续保持自己的心跳,让每个Broker都能感知到一个消费组内有哪些Consumer。原创 2024-03-21 07:33:08 · 314 阅读 · 0 评论 -
RocketMQ - 当Broker上的数据存储超过一定时间之后,磁盘数据是如何清理的?
然后如果是那种比较旧的、比如超过72小时的文件,就会被删除掉,也就是说,默认来说,broker只会给你把数据保留3天而已,当然你也可以自己通过fileReservedTime来配置这个时间,要保留几天的时间。在清理文件的时候,他会具体判断一下,如果当前时间是预先设置的凌晨4点,就会触发删除文件的逻辑,这个时间是默认的;在删除文件的时候,无非就是对文件进行遍历,如果一个文件超过72小时都没修改过了,此时就可以删除了,哪怕有的消息你可能还没消费过,但是此时也不会再让你消费了,就直接删除掉。原创 2024-03-20 07:33:44 · 158 阅读 · 0 评论 -
RocketMQ - RocketMQ是如何实现同步刷盘以及异步刷盘两种策略的?
上面代码我们就看的很清晰了,其实他里面是根据你配置的两种不同的刷盘策略分别处理的,我们先看第一种,就是同步刷盘的策略是如何处理的。FlushCommitLogService其实是一个线程,他是个抽象父类,他的子类是CommitRealTimeService,所以真正唤醒的是他的子类代表的线程。比如是同步刷盘还是异步刷盘,如果是同步刷盘,那么此时就会直接把内存里的数据写入磁盘文件,如果是异步刷盘,那么就是过一段时间之后,再把数据刷入磁盘文件里去。那么今天我们来看看底层到底是如何执行不同的刷盘策略的。原创 2024-03-20 07:33:26 · 138 阅读 · 0 评论 -
RocketMQ - 一条消息写入CommitLog文件之后,如何实时更新索引文件?
也就是说,在这个线程里,每隔1毫秒,就会把最近写入CommitLog的消息进行一次转发,转发到ConsumeQueue和IndexFile里去,通过的是doReput()方法来实现的,我们再看doReput()方法里的实现逻辑,先看下面源码片段。因此到这里为止,基本就看明白了,当我们把消息写入到CommitLog之后,有一个后台线程每隔1毫秒就会去拉取CommitLog中最新更新的一批消息,然后分别转发到ConsumeQueue和IndexFile里去,这就是他底层的实现原理。原创 2024-03-19 08:03:44 · 54 阅读 · 0 评论 -
RocketMQ - 当Broker获取到一条消息之后,它是如何存储这条消息的?
CommitLog文件的存储目录是在${ROCKETMQ_HOME}/store/commitlog下的,里面会有很多的CommitLog文件,每个文件默认是1GB大小,一个文件写满了就创建一个新的文件,文件名的话,就是文件中的第一个偏移量,如下面所示。接着其实会对消息做出一通处理,包括设置消息的存储时间、创建全局唯一的消息ID、计算消息的总长度,然后会走一段很关键的源码,把消息写入到MappedFile里去,这个其实我们之前还讲解过里面的黑科技,看下面的源码。原创 2024-03-19 08:03:23 · 64 阅读 · 0 评论 -
RocketMQ - 发送消息时Producer是如何选择MessageQueue去发送的?
Producer发送消息的时候,其实会先检查一下要发送消息的Topic的路由数据是否在本地缓存,如果不在的话,就会通过底层的Netty网络通信模块去发送一个请求到NameServer去拉取Topic路由数据,然后缓存在Producer的本地。之前介绍过,发送消息的核心源码是在DefaultMQProducerImpl.sendDefaultImpl()方法中的,在这个方法里,只要你获取到了Topic的路由数据,不管从本地缓存获取的,还是从NameServer拉取到的,接着就会执行下面的核心代码。原创 2024-03-18 08:39:57 · 345 阅读 · 0 评论 -
RocketMQ - Broker的注册及心跳检测
首先我们看一下Broker中的发送注册请求给NameServer的一个源码入口,其实就是在BrokerController.start()方法中,在BrokerController启动的时候,他其实并不是仅仅发送一次注册请求,而是启动了一个定时任务,会每隔一段时间就发送一次注册请求。上面这块代码,其实是启动了一个定时调度的任务,他默认是每隔30s就会执行一次Broker注册的过程,上面的registerNameServerPeriod是一个配置,他默认的值就是30s一次。原创 2024-03-18 08:39:30 · 518 阅读 · 0 评论 -
RocketMQ - Broker启动的时候都做了什么?
很明显,套路是一样的,broker在这里启动的时候也是先搞了几个核心的配置组件,包括了broker自己的配置、broker作为一个netty服务器的配置、broker作为一个netty客户端的配置、broker的消息存储的配置。我们之前启动broker的时候,其实都是要自定义一个broker配置文件的,然后用mqbroker启动的时候,都是要用-c选项带上自己的配置文件地址的,就是在上面的代码中,他会读取我们自定义的配置文件,填充到他的配置类里去。因为这些都不是最核心的一些代码,就是接着往下看就是了!原创 2024-03-16 09:27:18 · 120 阅读 · 0 评论 -
RocketMQ - NameServer是如何初始化基于Netty的网络通信架构的?
这个就非常不得了了,很明显,他就是构造了一个NettyRemotingServer,也就是Netty网络服务器。但是我们有一点是可以肯定的,仅仅创建出来一个NamesrvController,那绝对是不够的,肯定后续还有一些关键的代码,必须要启动他里面的Netty服务器才是核心的工作,这样他才能接受网络请求!既然是初始化,那么我们可以大胆的推测下,NamesrvController里我们最为关注的,不就是Netty服务器么,那么这个初始化的地方,是不是就是把他内部的Netty服务器给初始化构造出来了呢?原创 2024-03-16 09:27:04 · 32 阅读 · 0 评论 -
RocketMQ - NameServer在启动的时候都会解析哪些配置信息?
从他的类名,我们就可以推测出来,NamesrvConfig包含的是NameServer自身运行的一些配置参数,NettyServerConfig包含的是用于接收网络请求的Netty服务器的配置参数。上面的代码如果看懂了,我来给大家举个例子,比如说你在启动NameServer的时候,用-c选项带上了一个配置文件的地址,然后此时他启动的时候,运行到上面的代码,就会把你配置文件里的配置,放入两个核心配置类里去。看明白上面两个核心配置类之后,接着我们就可以继续往下看代码,看看那两个核心配置类的配置都是如何解析的。原创 2024-03-15 08:19:37 · 32 阅读 · 0 评论 -
RocketMQ - 如何在本地IDEA中启动及调试RocketMQ?
接着我们来修改一下RocketMQ自带的Producer示例程序,把RocketMQ nameserver的地址修改成我们自己的地址,接着我们执行运行上面的程序就可以了,他会发送1条消息到Broker里去,我们观察一下控制台的日志打印,可以看到下面的内容,就说明我们已经成功的把消息发送到Broker里去了。而我们要配置的是Environment Variables,就是环境变量,我们在上图中找到这个东西,他右边有一个按钮,大家可以点击一下,就会进入到一个添加环境变量的界面中去,大家看下面的图示。原创 2024-03-15 08:19:15 · 262 阅读 · 0 评论 -
RocketMQ - 如何处理消费系统故障导致RocketMQ消息积压问题?
针对这种紧急的线上事故,一般来说有几种方案可以快速搞定它,如果这些消息你是允许丢失的,那么此时你就可以紧急修改消费者系统的代码,在代码里对所有的消息都获取到就直接丢弃,不做任何的处理,这样可以迅速的让积压在MQ里的百万消息被处理掉,只不过处理方式就是全部丢弃而已。然后新的Topic有20个MessageQueue,然后再部署20台临时增加的消费者系统,去消费新的Topic后写入数据到NoSQL里去,这样子也可以迅速的增加消费者系统的并行处理能力,使用一个新的Topic来允许更多的消费者系统并行处理。原创 2024-03-14 07:46:02 · 100 阅读 · 0 评论 -
RocketMQ - 在RocketMQ的生产实践中积累的各种一手经验总结
举个例子,比如我们都知道现在常见的外卖平台有美团、饿了么,还有别的一些外卖,那么加入你现在一个系统要发送外卖订单数据到MQ里去,就可以针对性的设置tags,比如不同的外卖数据都到一个"waimaiOrderTopic"里去,但是不同类型的外卖可以有不同的tags,meituan_waimai、eleme_waimai等等。此外,还可以开启消费者的批量消费功能,就是设置consumeMessageBatchMaxSize参数,他默认是1,但是你可以设置的多一些,那么一次就会给你回调函数一批消息来给你处理了。原创 2024-03-12 07:41:36 · 96 阅读 · 0 评论 -
RocketMQ - 基于延迟消息机制优化大量订单的定时退款扫描问题!
我们先考虑一个正常的电商购物流程,一般来说我们作为用户在一个点上APP上都会选择一些商品加入购物车,然后对购物车里选择的一些商品统一下一个订单,此时后台的订单系统必然会在订单数据库中创建一个订单。但是我们下了一个订单之后,虽然订单数据库里会有一个订单,订单的状态却是"待支付"状态,因为此时你还没有支付这个订单,我们的订单系统其实也在等待订单用户完成这个订单的支付。这里就有两种可能了,一种是用户下单之后立马就支付掉了,那么接着订单系统可以走后续的流程,比如通过MQ发送消息通知优惠券系统给用户发放优惠券原创 2024-03-12 07:41:09 · 526 阅读 · 0 评论 -
RocketMQ - 为什么基于 RocketMQ 进行订单库数据同步时会消息乱序?
当消费者获取消息的时候,可能会部署多台机器组成一个Consumer Group,对于Consumer Group中的每台机器都会负责消费一部分MessageQueue的消息,所以可能一台机器从ConsumerQueue1中获取消息,一台机器从ConsumerQueue2中获取消息,所以完全有可能一个消费者节点先获取了后发到MQ中的消息进行处理。完全可以根据订单id来进行判断,我们可以往MQ里发送消息的时候,根据订单id来判断一下,如果订单id相同,你必须保证他进入同一个MessageQueue。原创 2024-03-08 08:52:24 · 62 阅读 · 0 评论 -
RocketMQ - 如果优惠券系统的数据库宕机,如何用死信队列解决这种异常场景?
假设我们的MQ使用都没有问题,但是如果我们的优惠券系统的数据库宕机了呢?因为我们一直都是假设了一个场景,就是订单支付成功之后会推消息到MQ,然后优惠券系统、红包系统会从MQ里获取消息去执行后续的处理,比如发红包或者发优惠券。那么如果这个时候,优惠券系统的数据库宕机了,就必然会导致我们从MQ里获取到消息之后是没办法进行处理的。原创 2024-03-08 08:52:05 · 47 阅读 · 0 评论 -
RocketMQ - 从 RocketMQ 底层原理分析为什么会重复发优惠券?
前面我们详细分析了MQ的消息出现重复的问题,接下来就要看看到底该如何去避免MQ中的消息进行重复处理。要解决这个问题,需要先了解一下幂等性,所谓幂等性机制,就是用来避免对同一个请求或者同一条消息进行重复处理的机制,意思就是比如你的一个接口,如果别人对一次请求重试了多次来调用你的接口,你的接口必须保证自己系统的数据是正常的,不能多出来一些重复的数据,这就是幂等性的意思。那么对于我们的MQ而言,就是你从MQ里获取消息的时候,要保证对同一个消息只能处理一次,不能重复处理多次,导致出现重复的数据。原创 2024-03-07 08:24:02 · 40 阅读 · 0 评论 -
RocketMQ - Consumer消息零丢失方案:手动提交offset + 自动故障转移
假设下游消费者系统已经获取了消息,但是消息目前还在他的内存里,还没有执行业务逻辑,此时他就直接提交了这条消息的offset到broker去说自己已经处理过了,然后这个时候下游消费者系统突然就宕机了,内存里的消息没有了,业务逻辑也没有执行,结果broker已经收到他提交的消息offset了,还以为他已经处理完这个消息了。所以在这个情况下,如果你对一批消息处理完毕了,然后再提交消息的offset给broker,接着消费者系统宕机了,此时是不会丢失消息的。原创 2024-03-07 08:23:37 · 195 阅读 · 0 评论 -
RocketMQ - Broker消息零丢失方案:同步刷盘 + Raft协议主从同步
此时可能下游消费者系统还没来得及获取这条消息,然后恰巧在此时,你的这条消息仅仅停留在os cache中,还没进入到ConsumeQueue磁盘文件里,然后此时这台机器突然宕机了,os cache中的数据全部丢失,此时必然导致你的消息丢失了。所以在异步刷盘的模式下,我们的写入消息的吞吐量是极高的,毕竟只要进入了os cache这个内存就可以了,写消息得到性能就是写内存的性能,但是这种情况下,可能会导致数据的丢失。调整之后,我们写入MQ的每条消息,只要MQ告诉我们写入成功了,那么他们就是已经进入了磁盘文件了。原创 2024-03-06 07:49:36 · 72 阅读 · 0 评论 -
RocketMQ - 发送消息零丢失方案:RocketMQ事务消息的实现流程分析
RocketMQ有一个非常强悍有力得到功能,就是事务消息,凭借这个事务级的消息机制,就可以让我们保证生产者推送出去的消息一定会成功写入MQ里,绝不会半路就搞丢了。首先以一个订单系统为例,假设他收到了一个订单支付成功的通知之后,他必然是需要在自己的订单数据库里做一些增删改查操作的,比如更新订单状态之类的。可能你会觉得,订单系统不就是先在自己的数据库做一些操作,然后直接发个消息到MQ去,让其他订阅这个Topic的系统去从MQ获取消息做对应的处理就可以了吗?其实还真不是这么简单,在基于RocketMQ的事务消息机原创 2024-03-06 07:49:16 · 432 阅读 · 0 评论 -
RocketMQ - 从RocketMQ全链路分析一下为什么用户支付后没收到红包?
现在我们假设消费者系统已经获取到了消息,然后消息此时就在他的内存里,正准备运行代码去做业务逻辑,默认情况下,MQ的消费者可能会自动提交已经消费的offset,那么如果此时你还没处理这个消息的情况下,MQ的消费者可能直接自动给你提交这个消息的offset到broker了,标识为已经成功处理了这个消息。答案是可能会丢失的,比如订单系统在推送消息到RocketMQ的过程中,是通过网络去进行传输的,但是这个时候恰巧可能网络发生了抖动,就导致这次网络通信失败了,于是这个消息必然就没有成功投递给MQ。原创 2024-03-05 08:20:27 · 37 阅读 · 0 评论 -
RocketMQ - 消费者到底是根据什么策略从Master或Slave上拉取消息的?
消费消息,可以从Master Broker拉取,也可以从Slave Broker拉取,那到底什么时候从Master Broker拉取,什么时候从Slave Broker拉取?之前有提到刚开始消费者都是从Master Broker机器上去拉取消息的,然后如果Master Broker机器觉得自己负载比较高,就会告诉消费者机器,下次可以从Slave Broker机器去拉取。原创 2024-03-05 08:20:08 · 140 阅读 · 0 评论 -
RocketMQ - 深入研究一下消费者是如何获取消息处理以及进行ACK
另外Push模式下有一个请求挂起和长轮询的机制,当你的请求发送到Broker,结果Broker发现没有新的消息给你处理的时候,就会让请求线程挂起,默认是挂起15秒,然后这个期间他会有后台线程每隔一会儿就去检查一下是否有新的消息给你,另外如果在这个挂起过程中,如果有新的消息到达了,会主动唤醒挂起的线程,然后把消息返回给你。接着介绍一个概念,就是对于一个消费组而言,他获取到一条消息之后,如果消费组内部有多台机器,到底是只有一台机器可以获取到这个消息,还是每台机器都可以获取到这消息?原创 2024-03-04 00:25:16 · 140 阅读 · 0 评论 -
RocketMQ - 深入研究一下Broker是如何持久化存储消息的
然后呢,当你的Broker收到一条消息写入了CommitLog之后,其实他同时会将这条消息在CommitLog中的物理位置,也就是一个文件偏移量,就是一个offset,写入到这条消息所属的MessageQueue对应的ConsumeQueue文件中去。另外,数据写入CommitLog文件的时候,其实不是直接写入底层的物理磁盘文件的,而是先进入OS的PageCache内存缓存中,然后后续由OS的后台线程选一个时间,异步化的将OS PageCache内存缓冲中的数据刷入底层的磁盘文件。原创 2024-03-04 00:24:50 · 135 阅读 · 0 评论 -
RocketMQ - 深入研究一下生产者到底如何发送消息的
一旦打开了这个开关,那么他会有一个自动容错机制,比如如果某次访问一个Broker发现网络延迟有500ms,然后还无法访问,那么就会自动回避访问这个Broker一段时间,比如接下来的300ms内,就不会访问这个Broker了。这样的话,就可以避免一个Broker故障之后,短时间内生产者频繁的发送消息到这个故障的Broker上去,出现较多次的异常,而是在一个Broker故障之后,自动回避一段时间不要访问这个Broker,过段时间再去访问他。原创 2024-03-01 08:05:21 · 53 阅读 · 0 评论 -
RocketMQ - 搭建RocketMQ
这个参数是用来控制进程的swap行为的,简单来说就是os会把一部分磁盘空间作为swap区域,然后如果有的进程现在可能不是太活跃,就会被操作系统把进程调整为睡眠状态,把进程中的数据放入磁盘上的swap区域,然后让这个进程把原来占用的内存空间腾出来,交给其他活跃运行的线程来使用。这个是用来控制linux上的最大文件连接数的,默认值可能是1024,一般肯定是不够的,因为你在大量频繁的读写磁盘文件的时候,或者进行网络通信的时候,都会跟这个参数有关系。原创 2024-03-01 08:03:09 · 40 阅读 · 0 评论 -
RocketMQ - Broker的主从架构原理是什么
这个时候就对消息的写入和获取都有一定的影响了,但是其实本质上而言,Slave Broker也是跟Master Broker一样有一份数据在的,只不过Slave Broker上的数据可能有部分没来得及从Master Broker同步,但是此时RocketMQ可以实现直接自动将Slave Broker切换成Master Broker吗?因为消息写入全部是发送到Master Broker的,然后消息获取也可以从Master Broker获取,只不过有一些消息获取可能从Slave Broker去获取。原创 2024-02-27 13:34:02 · 99 阅读 · 0 评论 -
RocketMQ - 消息中间件路由中心的架构原理
结果此时突然有一个Broker挂了,120s没有发送心跳给NameServer,NameServer是知道现在只有9个Broker了,但是此时其他系统是不知道只有9个Broker的,还以为有10个Broker,此时可能某个系统就会发送消息到那个已经挂掉的Broker上去,此时是绝对不可能成功发送消息的。有两种办法,第一种是NameServer会主动发送请求给所有的系统,告诉他们Broker信息,但是这种方法明显不靠谱,因为NameServer怎么知道要推送Broker信息给哪些系统呢?原创 2024-02-26 15:00:36 · 34 阅读 · 0 评论 -
RocketMQ - RocketMQ的架构原理和使用方法
然后对于业务系统而言,如果要发送消息到Broker,会找NameServer去获取路由信息,就是集群里有哪些Broker等信息,如果系统要从Broker获取信息,也会找NameServer获取路由,去找到对应的Broker获取消息。既然如此,MQ就得存储大量的消息,可能是几百万条,可能是几亿条,甚至是万亿条,这么多的消息在一台机器上肯定是没有办法存储的,那么RocketMQ是如何分布式存储海量消息的呢?对于系统来说,要发送消息到MQ里去,还要从MQ里消费消息,那么怎么知道有哪些Broker?原创 2024-02-26 08:30:09 · 430 阅读 · 0 评论 -
RocketMQ - 什么是RocketMQ
RocketMQ是一个低延时、高可靠、可伸缩、易于使用的分布式消息中间件,是由阿里巴巴开源捐献给Apache的顶级项目。RocketMQ具有高吞吐、低延迟、海量消息堆积等优点,同时提供顺序消息、事务消息、定时消息、消息重试于追踪等功能,非常适合在电商、金融等领域使用。原创 2020-05-23 09:47:09 · 649 阅读 · 1 评论