米乐游戏下载:事例共享|出产环境MQ集群一个十分怪异的消费推迟排查

   刊发时间:2023-02-25 21:20:17   来源:乐米体育彩票 作者:米6体育官方网站

  某一天,项目组一个搭档向我反应,他们运用公司的数据同步产品将MySQL数据同步到MQ集群,然后运用顾客将数据再同步到ES,反应数据同步推迟严峻,但对应的消费组确没有积压,但最近最近几分钟的数据都没有同步过来。

  那问题来了,消费端没有消费积压,而且经过检查数据同步渠道该经过使命的同步状况,相同显现没有积压,那是为什么呢?

  遇到这个问题,咱们应该冷静下来,剖析一下其大约的数据流向图,整理后如下图所示:

  经过开始的确诊,从数据同步产品检查Binlog同步无推迟、MQ消费无积压,那为什么终究Es集群中的数据与MySQL有高达几分钟的推迟呢?

  依据上图几个要害组件数据同步推迟的检测,基本就排除了数据同步组件、MQ消费端自身消费的问题,问题的症结应该便是数据同步组件成功将数据写入到MQ集群,而且MQ集群回来了写入成功,但消费端并没有及时感知这个音讯,也便是说音讯尽管写入到MQ集群,但并没有抵达消费行列。

  因为假如数据同步组件假如没有写入成功,则MySQL Binlog日志就会呈现推迟。但假如是MQ消费端的问题,则MQ渠道也会显现消费组积压。

  检查主题的计算信息时发现其时体系的时刻为19:01分, 但主题最新的写入时刻才是18:50,两者之间相差将近10分钟。

  补白:上述界面是咱们公司内部的音讯运营办理渠道,其实底层是调用了RocketMQ供给的topicStatus指令。

  在这儿我假定咱们对RocketMQ底层的完成原理还不是特别了解,在这样的情况下,我觉得咱们应该首要摸清楚topicStatus这个指令回来的minOffset、maxOffset以及lastUpdate这些是的详细获取逻辑,只要了解了这些,咱们才干追本溯源,终究找到解决办法。

  在这个场景中,咱们能够经过对topicStatus指令进行解析,然后探求其背面的完成原理。

  我也注意到剖析源码尽管能直抵本相,但阅览起来太粗糙,所以我接下来的文章会尽量防止通篇的源码解读,取而代之的是只点出源码的入口处,其旁支细节将经过时序图获流程图,便利感兴趣的读者朋友去探求,我要点进行常识点的提炼,下降咱们的学习本钱。

  假如咱们想成体系的研讨RocketMQ,想将音讯中间件当成自己作业的闪光点,强烈建议购买我的两本关于RocketMQ的数据:《RocketMQ技术内情》与《RocketMQ实战》。

  从上述时序图咱们能够得知,调用DefaultMessageStore的getMaxOffsetInQueue办法,首要是依据主题、行列ID获取ConsumeQueue目标(在RocketMQ中一个主题的一个行列会对应一个ConsumeQueue,代表一个消费行列),也便是这儿获取的偏移量指的是顾客行列中的偏移量,而不是Commitlog文件的偏移量。

  假如是找最大偏移量,就从该行列中的找到最终一个文件,去获取器最大的有用偏移量,也便是等于文件的开始偏移量(fileFromOffset)加上该文件其时最大可读的偏移量(readPosition),故引起这张时序图一个十分要害的点,便是怎么获取消费行列最大的可读偏移量,代码见MappedFile的getReadPosition:

  今日的主角当然不让非ReputMessageService莫属,这儿先和咱们遍及一下一个最基本的常识:RocketMQ为了寻求极致的次序写,会将一切主题的音讯次序写入到一个文件(Commitlog文件),然后异步转发到ConsumeQueue(消费行列文件)、IndexFile(索引文件)。

  在深化介绍Commitlog文件的转发机制之前,我在这儿先问咱们一个问题:音讯是写入到内存就转发给ConsumeQueue,亦或是刷写到磁盘后再转发呢?

  依据转发位点reputFromOffset,从Commitlog文件中获取音讯的物理偏移量、音讯巨细,tags等信息转发到音讯消费行列、索引文件。

  故转发的要害就在于Commitlog的maxOffset的获取逻辑了,其完成时序图如下所示:

  这儿中心要点是getReadPosition办法的完成,在RocketMQ写Commitlog文件,为了进步写入功能,引入了内存级读写别离机制,详细的完成原理如下图所示:

  能够得知:wrotePosition是音讯写入到内存(pagecache或许堆外内存)都会更新,但一旦敞开了堆外内存机制,并不会取该值,所以咱们能够了解为当音讯写入到Pagecache中时,就能够被转发到音讯消费行列。

  紧接着咱们再看一下committedPosition的调用链,如下所示:

  本来在RocketMQ中,假如敞开了transientStorePoolEnable机制,音讯先写入到堆外内存,然后就会向音讯发送者回来发送成功,然后会有一个异步线程(CommitRealTimeService)守时将音讯(默许200ms一次循环)提交到FileChannel,即更新committedPosition的值,音讯就会转发给消费行列,然后顾客就能够进行消费。

  因为咱们公司为了进步RocketMQ的资源利用率,进步RocketMQ的写入功能,咱们敞开了transientStorePoolEnable机制,音讯发送端写入到堆外内存,就会回来写入成功,这样MySQL Binlog数据同步并不会发生推迟,那这儿的问题,无非就2个:

  因为现在我暂时对底层存储写入的原理还知道不行深化,对相关体系收集目标不行灵敏,其时首要剖析了一下线程栈,发现ReputMessageService线程一直在作业,估测可能是转发不及时,这块我还需要愈加深化去研讨,假如咱们对这块有其实了解,欢迎留言,我也会在后续作业中进步这块的技术,愈加深化去了解底层的原理。

  也便是现在知道了问题的表象原因,尽管底层原理还未通透,但现在足以辅导咱们更好的处理问题:将集群内音讯写入大的主题,迁移到其他负载较低的集群,然后下降该集群的写入压力,当迁移了几个主题后,果不其然,音讯抵达消费行列挨近实时,集群得以康复。

  温馨提示:中通内部的音讯运维渠道,能够随时将主题迁移到其他集群,而发送方、消费方使用无需重启使用即可感知。开源地址:欢迎咱们star

 

版权所有: 米乐游戏下载_乐米体育彩票_米6官方网站 

京ICP备05050114号      400-160-1670