RocketMQ —消费重试

消费者出现异常,消费某条消息失败时, Apache RocketMQ 会根据消费重试策略重新投递该消息进行故障恢复。本文介绍消费重试机制的原理、版本兼容性和使用建议。

一、应用场景​

Apache RocketMQ 的消费重试主要解决的是业务处理逻辑失败导致的消费完整性问题,是一种为业务兜底的策略,不应该被用做业务流程控制。建议以下消费失败场景使用重试机制:

推荐使用消息重试场景如下:

  • 业务处理失败,且失败原因跟当前的消息内容相关,比如该消息对应的事务状态还未获取到,预期一段时间后可执行成功。

  • 消费失败的原因不会导致连续性,即当前消息消费失败是一个小概率事件,不是常态化的失败,后面的消息大概率会消费成功。此时可以对当前消息进行重试,避免进程阻塞。

典型错误使用场景如下:

  • 消费处理逻辑中使用消费失败来做条件判断的结果分流,是不合理的,因为处理逻辑已经预见了一定会大量出现该判断分支。

  • 消费处理中使用消费失败来做处理速率限流,是不合理的。限流的目的是将超出流量的消息暂时堆积在队列中达到削峰的作用,而不是让消息进入重试链路。

二、应用目的​

消息中间件做异步解耦时的一个典型问题是如果下游服务处理消息事件失败,如何保证整个调用链路的完整性。Apache RocketMQ 作为金融级的可靠业务消息中间件,在消息投递处理机制的设计上天然支持可靠传输策略,通过完整的确认和重试机制保证每条消息都按照业务的预期被处理。

了解 Apache RocketMQ 的消息确认机制以及消费重试策略可以帮助您分析如下问题:

  • 如何保证业务完整处理消息:了解消费重试策略,可以在设计实现消费者逻辑时保证每条消息处理的完整性,避免部分消息出现异常时被忽略,导致业务状态不一致。

  • 系统异常时处理中的消息状态如何恢复:帮助您了解当系统出现异常(宕机故障)等场景时,处理中的消息状态如何恢复,是否会出现状态不一致。

三、消费重试策略概述​

消费重试指的是,消费者在消费某条消息失败后,Apache RocketMQ 服务端会根据重试策略重新消费该消息,超过一次定数后若还未消费成功,则该消息将不再继续重试,直接被发送到死信队列中。

消息重试的触发条件

  • 消费失败,包括消费者返回消息失败状态标识或抛出非预期异常。

  • 消息处理超时,包括在PushConsumer中排队超时。

消息重试策略主要行为

  • 重试过程状态机:控制消息在重试流程中的状态和变化逻辑。

  • 重试间隔:上一次消费失败或超时后,下次重新尝试消费的间隔时间。

  • 最大重试次数:消息可被重试消费的最大次数。

消息重试策略差异

根据消费者类型不同,消息重试策略的具体内部机制和设置方法有所不同,具体差异如下:

消费者类型重试过程状态机重试间隔最大重试次数
PushConsumer已就绪 处理中 待重试 提交 * 死信消费者分组创建时元数据控制。 无序消息:阶梯间隔 顺序消息:固定间隔时间消费者分组创建时的元数据控制。
SimpleConsumer已就绪 处理中 提交 死信通过API修改获取消息时的不可见时间。消费者分组创建时的元数据控制。

 

四、PushConsumer消费重试策略​

重试状态机

PushConsumer消费消息时,消息的几个主要状态如下:

Push消费状态机

  • Ready:已就绪状态。消息在Apache RocketMQ服务端已就绪,可以被消费者消费。

  • Inflight:处理中状态。消息被消费者客户端获取,处于消费中还未返回消费结果的状态。

  • WaitingRetry:待重试状态,PushConsumer独有的状态。当消费者消息处理失败或消费超时,会触发消费重试逻辑判断。如果当前重试次数未达到最大次数,则该消息变为待重试状态,经过重试间隔后,消息将重新变为已就绪状态可被重新消费。多次重试之间,可通过重试间隔进行延长,防止无效高频的失败。

  • Commit:提交状态。消费成功的状态,消费者返回成功响应即可结束消息的状态机。

  • DLQ:死信状态。消费逻辑的最终兜底机制,若消息一直处理失败并不断进行重试,直到超过最大重试次数还未成功,此时消息不会再重试,会被投递至死信队列。您可以通过消费死信队列的消息进行业务恢复。

消息重试过程中,每次重试消息状态都会经过已就绪>处理中>待重试的变化,两次消费间的间隔时间实际由消费耗时及重试间隔控制,消费耗时的最大上限受服务端系统参数控制,一般不应该超过上限时间。

消息间隔时间

最大重试次数

PushConsumer的最大重试次数由消费者分组创建时的元数据控制。

例如,最大重试次数为3次,则该消息最多可被投递4次,1次为原始消息,3次为重试投递次数。

重试间隔时间

  • 无序消息(非顺序消息):重试间隔为阶梯时间,具体时间如下:

    第几次重试与上次重试的间隔时间第几次重试与上次重试的间隔时间
    110秒97分钟
    230秒108分钟
    31分钟119分钟
    42分钟1210分钟
    53分钟1320分钟
    64分钟1430分钟
    75分钟151小时
    86分钟162小时

信息

若重试次数超过16次,后面每次重试间隔都为2小时。

  • 顺序消息:重试间隔为固定时间。

使用示例

PushConsumer触发消息重试只需要返回消费失败的状态码即可,当出现非预期的异常时,也会被SDK捕获。

SimpleConsumer simpleConsumer = null;//消费示例:使用PushConsumer消费普通消息,如果消费失败返回错误,即可触发重试。MessageListener messageListener = new MessageListener() {@Overridepublic ConsumeResult consume(MessageView messageView) {System.out.println(messageView);//返回消费失败,会自动重试,直至到达最大重试次数。return ConsumeResult.FAILURE;}};

五、SimpleConsumer消费重试策略​

重试状态机

SimpleConsumer消费消息时,消息的几个主要状态如下:

SimpleConsumer状态机

  • Ready:已就绪状态。消息在Apache RocketMQ服务端已就绪,可以被消费者消费。

  • Inflight:处理中状态。消息被消费者客户端获取,处于消费中还未返回消费结果的状态。

  • Commit:提交状态。消费成功的状态,消费者返回成功响应即可结束消息的状态机。

  • DLQ:死信状态。消费逻辑的最终兜底机制,若消息一直处理失败并不断进行重试,直到超过最大重试次数还未成功,此时消息不会再重试,会被投递至死信队列。您可以通过消费死信队列的消息进行业务恢复。

和PushConsumer消费重试策略不同的是,SimpleConsumer消费者的重试间隔是预分配的,每次获取消息消费者会在调用API时设置一个不可见时间参数 InvisibleDuration,即消息的最大处理时长。若消息消费失败触发重试,不需要设置下一次重试的时间间隔,直接复用不可见时间参数的取值。 

simpleconsumer重试

由于不可见时间为预分配的,可能和实际业务中的消息处理时间差别较大,您可以通过API接口修改不可见时间。

例如,您预设消息处理耗时最多20 ms,但实际业务中20 ms内消息处理不完,您可以修改消息不可见时间,延长消息处理时间,避免消息触发重试机制。

修改消息不可见时间需要满足以下条件:

  • 消息处理未超时

  • 消息处理未提交消费状态

如下图所示,消息不可见时间修改后立即生效,即从调用API时刻开始,重新计算消息不可见时间。 

修改不可见时间

最大重试次数

SimpleConsumer的最大重试次数由消费者分组创建时的元数据控制。

消息重试间隔

消息重试间隔=不可见时间-消息实际处理时长

SimpleConsumer 的消费重试间隔通过消息的不可见时间控制。例如,消息不可见时间为30 ms,实际消息处理用了10 ms就返回失败响应,则距下次消息重试还需要20 ms,此时的消息重试间隔即为20 ms;若直到30 ms消息还未处理完成且未返回结果,则消息超时,立即重试,此时重试间隔即为0 ms。

使用示例

SimpleConsumer 触发消息重试只需要等待即可。

 //消费示例:使用SimpleConsumer消费普通消息,如果希望重试,只需要静默等待超时即可,服务端会自动重试。List<MessageView> messageViewList = null;try {messageViewList = simpleConsumer.receive(10, Duration.ofSeconds(30));messageViewList.forEach(messageView -> {System.out.println(messageView);//如果处理失败,希望服务端重试,只需要忽略即可,等待消息再次可见后即可重试获取。});} catch (ClientException e) {//如果遇到系统流控等原因造成拉取失败,需要重新发起获取消息请求。e.printStackTrace();}

六、使用建议​

合理重试,避免因限流等诉求触发消费重试

​上文应用场景中提到,消息重试适用业务处理失败且当前消费为小概率事件的场景,不适合在连续性失败的场景下使用,例如消费限流场景。

  • 错误示例:如果当前消费速度过高触发限流,则返回消费失败,等待下次重新消费。

  • 正确示例:如果当前消费速度过高触发限流,则延迟获取消息,稍后再消费。

合理控制重试次数,避免无限重试

虽然Apache RocketMQ支持自定义消费重试次数,但是建议通过减少重试次数+延长重试间隔来降低系统压力,避免出现无限重试或大量重试的情况。

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

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

相关文章

DICOM 文件中,VR,VL,SQ,图像二进制的几个注意点

DICOM 文件的结构&#xff0c;在网上有很多的学习资料&#xff0c;这里只介绍些容易混淆的概念&#xff0c;作为回看笔记。 1. 传输语法 每个传输语法&#xff0c;起都是表达的三个概念&#xff1a;大小端、显隐式、压缩算法 DICOM Implicit VR Little Endian: 1.2.840.1000…

解决VSCode打开终端Terminal闪退的问题

一、背景 在新电脑上使用了VSCode&#xff0c;但是一打开Terminal&#xff0c;Terminal马上就消失了&#xff0c;在网上找了很久&#xff0c;都没有找到对应的分析 二、解决思路 首先&#xff0c;是从这个文档中找到了灵感&#xff0c;这个文档里面汇集了大部分的问题&#…

孩子都能学会的FPGA:第三十二课——用FPGA实现一个通用的SPI主机发送模块

&#xff08;原创声明&#xff1a;该文是作者的原创&#xff0c;面向对象是FPGA入门者&#xff0c;后续会有进阶的高级教程。宗旨是让每个想做FPGA的人轻松入门&#xff0c;作者不光让大家知其然&#xff0c;还要让大家知其所以然&#xff01;每个工程作者都搭建了全自动化的仿…

二百一十五、Flume——Flume拓扑结构之复制和多路复用的开发案例(亲测,附截图)

一、目的 对于Flume的复制和多路复用拓扑结构&#xff0c;进行一个小的开发测试 二、复制和多路复用拓扑结构 &#xff08;一&#xff09;结构含义 Flume 支持将事件流向一个或者多个目的地。 &#xff08;二&#xff09;结构特征 这种模式可以将相同数据复制到多个channe…

微信生态下的私域流量载体有哪些?

私域流量的本质就是&#xff1a;降低我的获客成本&#xff0c;提高我产品服务的复购率&#xff0c;增加我和用户之间的粘性&#xff0c;挖掘用户的终身价值。 私域流量一般我们特指微信体系的个人号、公众号、社群和小程序&#xff0c;现在朋友圈和视频号也成为了打造微信私域…

HubSpot和AI的完美结合:解锁业务增长密码

随着数字化时代的发展&#xff0c;智能营销已经成为企业走向成功的关键之一。在这个领域的领先者之一&#xff0c;HubSpot积极整合人工智能&#xff08;AI&#xff09;技术&#xff0c;为数字营销、销售和服务带来了新的可能性。今天运营坛将带领大家深入探讨HubSpot和人工智能…

活动预告 | 微盟技术沙龙 - Elasticsearch 在微盟的实践 12/21/2023

微盟技术沙龙 「微盟技术沙龙」是由微盟研发中心发起并联合各方小伙伴为开发者举办的系列技术沙龙&#xff0c;从用户&#xff0c;产品&#xff0c;技术等方面与开发者进行交流。 微盟技术沙龙关注开发者在实际应用中遇到的问题。提供最真实的干货&#xff0c;以技术会友&…

GPU 性能测试软件:GPU-Z,2023 年 9 月 12 日更新

GPU-Z是一款用于Windows操作系统的免费工具&#xff0c;它用于查看和监控计算机的图形处理单元&#xff08;GPU&#xff09;信息。这个工具是专为计算机硬件爱好者、游戏玩家、系统管理员和技术支持人员设计的 GPU-Z 的特点 GPU信息&#xff1a;GPU-Z能够显示关于您计算机中G…

命令执行 [BUUCTF 2018]Online Tool1

打开题目 我们代码审计一下 if (isset($_SERVER[HTTP_X_FORWARDED_FOR])) { $_SERVER[REMOTE_ADDR] $_SERVER[HTTP_X_FORWARDED_FOR]; } 如果存在xxf头且不为空&#xff0c;则将xxf头内容&#xff08;真实的客户端ip&#xff09;赋给ROMOTE_ADDR&#xff08;代理服务器传过…

如何使用蜘蛛池蚂蚁SEO

​蜘蛛池是一种利用搜索引擎爬虫进行推广营销的方式。它的核心是建立一个能够吸引搜索引擎爬虫的网站群&#xff0c;这些网站能够产生大量的优质内容&#xff0c;并形成一个巨大的网站群&#xff0c;从而吸引更多的搜索引擎爬虫。 如何联系蚂蚁seo&#xff1f; baidu搜索&…

【C语言(十二)】

数据在内存中的存储 一、整数在内存中的存储 整数的2进制表示方法有三种&#xff0c;即 原码、反码和补码 有符号的整数&#xff0c;三种表示方法均有符号位和数值位两部分&#xff0c;符号位都是用0表示“正”&#xff0c;用1表示“负”&#xff0c;最高位的⼀位是被当做符号…

无参数RCE知识点

什么是无参数RCE&#xff1f; 无参rce&#xff0c;就是说在无法传入参数的情况下&#xff0c;仅仅依靠传入没有参数的函数套娃就可以达到命令执行的效果 核心代码 if(; preg_replace(/[^\W]\((?R)?\)/, , $_GET[code])) { eval($_GET[code]); } 这段代码的核心就是只…

西工大计院计算机系统基础实验二(配置gdb插件)

第二次实验是二进制炸弹实验&#xff0c;为了简化操作&#xff0c;并且让大家接下来能够按照作者之前已经为网安院写好的博客西工大网络空间安全学院计算机系统基础实验二&#xff08;清楚实验框架及phase_1&#xff09;-CSDN博客来走&#xff0c;大家需要下载一款好用的gdb插件…

canvas基本绘制对象

目录 绘制画布 设置画布 绘制圆形 绘制矩形填充渐变色 绘制文字及文字样式 绘制画布 <canvas id"canvas" width"800" height"600"></canvas> 设置画布 //获得画布元素var canvasdocument.getElementById(canvas);var ctxca…

基于Java (spring-boot)的二手物品交易平台

​ 一、项目介绍 1、管理员功能 &#xff08;1&#xff09;登录&#xff1a;管理员能够根据账号访问系统。 &#xff08;2&#xff09;用户管理&#xff1a;管理员可以添加、删除、修改用户信息&#xff0c;查看用户列表&#xff0c;对用户进行管理和控制。例如&#xff0c…

Python将Labelme文件的标注信息绘制到图片上

Python将Labelme文件的标注信息绘制到图片上 前言前提条件相关介绍实验环境Python将Labelme文件的标注信息绘制到图片上代码实现输出结果 前言 由于本人水平有限&#xff0c;难免出现错漏&#xff0c;敬请批评改正。更多精彩内容&#xff0c;可点击进入Python日常小操作专栏、O…

怎么把图片转文字?这几个图片转文字方法一定要知道!

怎么把图片转文字&#xff1f;无论是从书籍、网络还是社交媒体上&#xff0c;我们经常需要从图片中提取文字来进行复制、编辑或翻译。手动操作耗时耗力&#xff0c;效率低下&#xff0c;那么怎么把图片转文字呢&#xff1f;今天我将介绍三种不同的方法来实现图片转文字。 图片转…

OceanMind海睿思案例入选第二届中国数据治理年会“DCMM百项优秀案例”

近日&#xff0c;中国电子信息行业联合会在北京成功举办“第二届中国数据治理年会”。 本届大会以“数据强基、智领未来”为主题&#xff0c;汇聚我国数据治理领域的资深专家、学者、企业大咖同台论道&#xff0c;共话数据未来的发展与创新。 中新赛克海睿思作为DCMM3级乙方代…

HPM6750系列--总章

本栏目介绍先楫半导体出品的HPM6750芯片&#xff08;基于HPM6750evkmini开发板&#xff09; ​​​​​​​ 内容概述 HPM6750系列--第一篇 初识HPM6750 介绍HPM6750芯片信息&#xff0c;包括主频、内存、外设配置&#xff0c;并列举了各种开发工具和开发资源。 HPM6750系列--…