RocketMQ消费者没有成功消费消息的问题排查

news2024/12/24 8:15:47

背景

今天下游同事反馈,有一些以取消的订单库存还原异常了,导致部分商品库存没有还原。查日志发现没有收到还原消息,但是查看发送方是可以确认消息是已经发了的,那么是什么原因导致消费者没有收到,或者收到后没有处理消息呢。最后发现这些消息的状态都是NOT_ONLINE,原因是服务挂了,重启之后便可以重新消费了。让我们看看这个调查过程。

调查

消息丢失如何排查?当我们在使用mq的时候,经常会遇到消息消费异常的问题,原因有很多种,比如:

  • producer发送失败
  • consumer消费异常
  • consumer根本就没收到消息

「那么我们该如何排查了?」

其实借助RocketMQ-Dashboard就能高效的排查,里面有很多你想象不到的功能。

首先我们先查找期望消费的消息,查找的方式有很多种,根据消息id,时间等。

「消息没找到?」

说明proder发送异常,也有可能是消息过期了,因为rocketmq的消息默认保存72h,此时到producer端的日志进一步确认即可。

「消息找到了!」

接着看消息的消费状态,如下图消息的消费状态为NOT_ONLINE。

「NOT_ONLINE代表什么含义呢?」

别着急,我们一步步来分析,先看看TrackType到底有多少种状态。

public enum TrackType {
    CONSUMED,
    CONSUMED_BUT_FILTERED,
    PULL,
    NOT_CONSUME_YET,
    NOT_ONLINE,
    UNKNOWN
}

每种类型的解释如下:

类型

解释

CONSUMED

消息已经被消费

CONSUMED_BUT_FILTERED

消息已经投递但被过滤

PULL

消息消费的方式是拉模式

NOT_CONSUME_YET

目前没有被消费

NOT_ONLINE

CONSUMER不在线

UNKNOWN

未知错误

「怎么判定消息已经被消费?」

上一节我们讲到,broker会用一个map来保存每个queue的消费进度,「如果queue的offset大于被查询消息的offset则消息被消费,否则没有被消费」(NOT_CONSUME_YET)。

我们在RocketMQ-Dashboard上其实就能看到每个队列broker端的offset(代理者位点)以及消息消费的offset(消费者位点),差值就是没有被消费的消息。

当消息都被消费时,差值为0,如下图所示:

 「CONSUMED_BUT_FILTERED表示消息已经投递,但是已经被过滤掉了」。例如producer发的是topicA,tagA,但是consumer订阅的却是topicA,tagB。

「CONSUMED_BUT_FILTERED(消息已经被投递但被过滤)是怎么发生的呢?」

这个就不得不提到RocketMQ中的一个概念,「消息消费要满足订阅关系一致性,即一个consumerGroup中的所有消费者订阅的topic和tag必须保持一致,不然就会造成消息丢失」。

如下图场景,发送了4条消息,consumer1订阅了topica-taga,而consumer2订阅了topica-tab。consumer1消费q0中的数据,consumer2消费q1中的数据。

投递到q0的msg-1和msg-3只有msg-1能被正常消费,而msg-3则是CONSUMED_BUT_FILTERED。因为msg-3被投递到q0,但是consumer1不消费tagb的消息导致消息被过滤,造成消息丢失。

同理msg-2这条消息也会丢失。

「注意,还有一个非常重要的点」!

虽然消息消费失败了,但是消息的offset还会正常提交,即 「消息消费失败了,但是状态也会是CONSUMED」。

「RocketMQ认为消息消费失败需要重试的场景有哪些?」

  • 返回ConsumeConcurrentlyStatus.RECONSUME_LATER
  • 返回null
  • 主动或被动抛出异常

「那么消费失败的消息去哪了呢?」

当消息消费失败,会被放到重试队列中,Topic名字为%RETRY% + consumerGroup。

「Consumer没订阅这个topic啊,怎么才能消费到重试消息?」

其实在Consumer启动的时候,框架内部帮你订阅了这个topic,所以重试消息能被消费到。

「另外消息不是一直重试,而是每隔1段时间进行重试」

第几次重试

与上次重试的间隔时间

第几次重试

与上次重试的间隔时间

1

10 秒

9

7 分钟

2

30 秒

10

8 分钟

3

1 分钟

11

9 分钟

4

2 分钟

12

10 分钟

5

3 分钟

13

20 分钟

6

4 分钟

14

30 分钟

7

5 分钟

15

1 小时

8

6 分钟

16

2 小时

当消息超过最大消费次数16次,会将消息投递到死信队列中,死信队列的topic名为%DLQ% + consumerGroup。

「因此当你发现消息状态为CONSUMED,但是消费失败时,去重试队列和死信队列中找就行了」。

本篇文章如有帮助到您,请给「翎野君」点个赞,感谢您的支持。

首发链接:https://www.cnblogs.com/lingyejun/p/16997414.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/108691.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

算法刷题打卡第53天:排序数组---希尔排序

排序数组 难度:中等 给你一个整数数组 nums,请你将该数组升序排列。 示例 1: 输入:nums [5,2,3,1] 输出:[1,2,3,5]示例 2: 输入:nums [5,1,1,2,0,0] 输出:[0,0,1,1,2,5]希尔排…

六、Buffer缓冲区和Stream流

Buffer —— 缓冲区 JavaScript 提供了大量对字符串的便捷操作,但没有读取或操作二进制数据流机制,而在Node.js中可以直接用Buffer类提供的构造函数创建Buffer实例,一个Buffer实例代表一个缓冲区,Buffer的缓冲区专门用于存放二进制…

全球「数字游民」现状,有人已经72岁了

近年来,“数字游民”在国内越来越流行,特别是受疫情的影响,很多人对这种工作生活方式越来越喜欢,也越来越习惯,在此之前,当你告诉别人你是一名“数字游民”时,大家通常会认为你是没有工作的无业…

RocketMQ-双主双从集群+DashBorad搭建(云服务器)

文章目录一、理论垫基础1. NameServer 集群2. Producer集群3. Consumer集群4. Broker集群4.1 节点间数据同步 以及 消息的持久化4.2 Broker的集群模式4.2.1、单Master模式4.2.2、多Master模式4.2.3、多Master多Slave模式-异步复制4.2.4、多Master多Slave模式-同步双写最佳实践4…

APM32F103 RTC内部时钟源报警中断例程测试

APM32F103 RTC内部时钟源报警中断例程测试✨相关篇推荐《【开源电路】STM32F103VCT6开发板》📌关篇《APM32F103 RTC内部时钟源秒中断例程测试》📌本案例来源于官方的SDK固件包:https://www.geehy.com/support/apm32 🎈源码位置&am…

二极管:烧IC与我相干!

趁“羊”未到,还有心力接着上节继续讲。 话说,烧IC,不只本身IC烧,还火烧连营连带后端IC一并烧,为何呢!? 那得回到过去,必须翻翻《硬件先生》中的《电源知识-DC-DC》,从D…

GPU与CPU的性能比较及影响因素

CPU的主要指标是主频和线程。 Intel:后缀F表示无核显,后缀K代表可以超频,H代表移动端;AMD:后缀G代表有核显,后缀X代表加强版,后缀XT代表超级加强版。 CPU 常见计算操作: 数据加载、…

4.0、Hibernate-延迟加载 2

4.0、Hibernate-延迟加载 2 消费者 和 订单 属于 一对多 的 关系,通过上一章节 3.0 的内容我们知道了可以通过设置 customer 来实现延迟加载,本章节来介绍一下如何设置 orders 去实现延迟加载; one-to-many 的 lazy 默认是 true 是开启的&…

%29 身份认证

1、Web 开发模式 (1)、基于服务器渲染的开发模式:服务器发送给客户端的 HTML 页面,是在服务器通过字符串的拼接,动态生成的(企业级网站) (2)、基于前后端分离的开发模式&…

登录过程(vuex存储token、token持久化)

登录过程(vuex存储数据) 点击登录按钮通过表单校验 this.$refs.loginForm.validate(valid > {if (valid) {//按钮动画加载,禁用 this.loading true// 调用vuex的action发送登录请求this.$store.dispatch(user/login, this.loginForm).then(() > {this.$router.push({ p…

内存分配函数(动态内存分配)详解

目录 🎑为什么要进行动态内存开辟? 🎑malloc和free 🎠malloc函数 🎠free函数 🎠malloc函数和free函数的实际应用 🎑calloc函数 🎑realloc函数 🎠realloc函数的使用示例 &…

通过脚手架vue-cli创建一个vue项目

我需要在vue-demo文件下新建vue项目 步骤一 ①在该文件夹下打开集成终端 输入创建命令 命令 vue create 项目名称 ,注意不要使用驼峰命名法 如果是第一次配置,有面的提示,这里说你这样速度会很慢的,用不用镜像啊,这…

样品制备丨艾美捷硝酸盐/亚硝酸盐荧光法检测试剂盒

一氧化氮(NO)是由一氧化氮合酶(NOS)在生物系统中合成的。NOS是一种非常复杂的酶,作用于分子氧、精氨酸和NADPH,产生NO、瓜氨酸和NADP。这个过程需要五个额外的辅因子(FMN、FAD、血红素、钙调素和…

制造业ERP管理系统在企业采购管理中的作用是什么?

对于任何一家企业,采购都是头等大事。企业的采购工作往往是决定了企业产品的交货速度、成本和质量,特别是在制造行业,采购成本甚至占比产品成本的60%以上,降低采购成本是提高企业竞争力的关键。因此,对于企业采购领域的…

Effective C++条款34:区分接口继承和实现继承

Effective C条款34:区分接口继承和实现继承(Differentiate between inheritance of interface and inheritance of implementation)条款34:区分接口继承和实现继承1、纯虚函数2、虚函数(非纯)2.1 将默认实现…

2022 IoTDB Summit:中国核电刘旭嘉《工业时序数据库 Apache IoTDB 在核电的应用实践》...

12 月 3 日、4日,2022 Apache IoTDB 物联网生态大会在线上圆满落幕。大会上发布 Apache IoTDB 的分布式 1.0 版本,并分享 Apache IoTDB 实现的数据管理技术与物联网场景实践案例,深入探讨了 Apache IoTDB 与物联网企业如何共建活跃生态&#…

middlebury立体匹配评估使用方法总结(三)——线上版教程

系列文章目录 middlebury立体匹配评估使用方法总结(一)——网站说明 middlebury立体匹配评估使用方法总结(二)——python版离线教程 middlebury立体匹配评估使用方法总结(三)——线上版教程 文章目录系列文…

TableLayout布局

表格布局-TableLayout 1.TableLayout简介 1.简介 表格的形式,整齐可以嵌套继承于线性布局2.行数如何确定? tableRow,来指定行数列数由最多的那个决定layout_column来指定具体的列数,从0开始2.TableLayout的常见属性 所有的都是从0…

VMware ESxi 服务器迁移【手动版】

VMware ESxi 迁移【手动版】 应用场景 两个不同环境下的服务器进行迁移 因为不能直接对拷,需要在中间机上转一下 才有了这么一出 第一步 搭建NFS 在中间机上安装NFS(或者其他磁盘挂载方式) 目的呢是把源服务器上的系统拷贝到中间机上&#x…

android入门之broadcast

1. 前言 广播Broadcast是android四大组件之一。是用来互相通信(传递信息)的一种机制。 通信包括: a) 组件间(应用内)通信 b) 进程间通信 2. 广播Brocast的基本使用方式 广播发送者:Acvitity、Service等…