rocket新手一些常见问题

重试机制:RocketMQ 会自动触发重试, 是把消息怎么放到队列里面的,因为队列里面还有其他消息要投递不可能阻塞吧

RocketMQ 的设计非常巧妙,它并没有把失败的消息放回原队列的尾部,而是将其转移到了一个"独立的延迟队列"中。这样既保证了重试,又彻底避免了对原队列的阻塞。

具体原理如下:

1. 核心机制:独立的"重试队列"

当消费者处理消息失败(例如抛出异常或返回 RECONSUME_LATER)时,RocketMQ 会将这条失败的消息转移到一个专门针对该消费者组(ConsumerGroup)创建的独立 Topic 中。

  • 重试队列命名%RETRY%{ConsumerGroup}
  • 不阻塞原队列:因为失败的消息被移走了,原队列(原始 Topic)完全不受影响,Broker 会继续向消费者投递原队列里的后续新消息。

2. 底层实现:借助"延迟队列"实现时间间隔

你可能好奇,既然放到了重试队列,它是怎么做到"等一会儿再投递"的呢?

  • RocketMQ 内部有一个特殊的延迟 Topic:SCHEDULE_TOPIC_XXXX27。
  • 当消息进入重试流程时,Broker 会先把它存入这个延迟 Topic,并根据重试次数设置一个延迟级别(例如第 1 次重试延迟 10 秒,第 2 次延迟 30 秒,依此类推)7。
  • 延迟时间一到,Broker 内部的定时任务(ScheduleMessageService)会把这条消息从延迟队列中拿出来,再投递到 %RETRY%{ConsumerGroup} 重试队列中,供消费者再次拉取消费27。

3. 一直失败的终极兜底:死信队列(DLQ)

正如我们上一轮聊到的,如果这条消息在重试队列里反复重试,达到了最大次数(默认 16 次)依然失败,RocketMQ 就会停止重试,将其转入死信队列(%DLQ%{ConsumerGroup}。此时,消息不再自动投递,需要人工介入处理,从而彻底避免"毒药消息"无限占用重试队列的资源。

补充说明:顺序消息的"例外"

需要特别注意的是,上述"不阻塞"的机制主要针对无序(并发)消息

如果你使用的是顺序消息 ,为了保证严格的先后顺序,一旦某条消息消费失败,RocketMQ 会采用"原地重试"的策略(默认每隔 1 秒重试一次)。在这种特定场景下,当前队列的后续消息确实会被阻塞,直到这条消息重试成功或达到最大重试次数2。这也是为什么在使用顺序消息时,必须极力避免消费逻辑出现常态化失败的原因5

RocketMQ 的事务消息

rocketmq的事务消息一般是最终一致性

1.他在生产者上产生一个半提交消息,就是事务成功后要通知下游的信息

  1. 然后开启 事务

  2. 执行本地的事务

4,.提交或回滚, 回滚消息就不会继续投递了,半消息是不可见的,也是不会投递的

提交后就会正常投递下游消费者

  1. 如果你中途异常没有commit 或 rollback

事务半消息会回查,需要自己写一个回查的类

  1. 完成

你可能会疑惑不是跟正常投递一样, 但不同的点在于5 事务要保证同时成功或同时失败 你本地业务执行数据库本地提交了但没有发送消息就断电了会导致事务失效.

他可以保证回查导致消息一定发送

那一直失败会怎么样先投递其他消息

1. 如果是"回查一直失败"(生产者宕机或网络异常)

当生产者发送了半消息(Half Message),但因为宕机或网络问题,迟迟没有返回 Commit 或 Rollback,RocketMQ 服务端(Broker)就会启动事务回查机制

  • 不会放到队列尾部 :这条半消息此时对消费者是不可见的,它被暂存在 Broker 内部的系统 Topic 中,根本不会进入正常的消费队列,所以不存在"放到队尾"的说法。
  • 持续回查与最终回滚 :Broker 会按照指定的时间间隔(如每 10 秒)主动发起回查请求。如果经过多次回查(默认 15 次,或持续 24 小时),生产者依然无法给出确切状态(一直返回 Unknown 或无响应),Broker 会彻底放弃,直接将这条半消息删除(Rollback),并记录日志。这条消息将永远不会被投递给下游消费者26。

2. 如果是"消费者消费一直失败"(下游服务处理异常)

如果半消息已经成功 Commit,消费者拉取到了消息,但在执行本地业务逻辑时一直失败(比如数据库死锁、第三方接口报错等),这属于普通消息的消费重试机制

  • 重试机制:RocketMQ 会自动触发重试,将消息重新投递给消费者。重试的间隔是递增的(比如 10s, 30s, 1min... 2h),而不是简单地放到当前队列的尾部1。
  • 死信队列(DLQ) :如果经过多次重试(默认 16 次)依然失败,RocketMQ 会认为这条消息是"无法处理的毒药消息",将其转入死信队列(Dead Letter Queue)。此时,消息不会再自动投递,需要由人工介入核对,通过补偿流程来保障数据的最终准确1
相关推荐
卢锡荣42 分钟前
单芯掌控多口互联|乐得瑞 LDR6020 PD3.1 多通道 Type‑C 控制 SOC 芯片
c语言·开发语言
yume_sibai44 分钟前
02-Rust 所有权与借用深入解析(底层原理 + 借用检查器 + 生命周期 + 内部可变性)
开发语言·后端·rust
xxwxx__1 小时前
深入理解 C++ STL:stack、queue 与 deque 从使用到底层实现全解析
开发语言·c++·算法
Highcharts.js1 小时前
甘特图纵向任务、横向时间显示图表可视化开发|Highcharts甘特图示例
开发语言·前端·javascript·可视化·甘特图·数据可视化·highcharts
骇客野人1 小时前
Springboot 的 配置文件 application.yml 和 bootrap.yml 的由来和作用
java·spring boot·后端
wuminyu1 小时前
JVM锁膨胀与Futex源码解析
java·linux·c语言·jvm·c++
郝学胜-神的一滴1 小时前
C++11 工程级应用 08:Lambda表达式与Tuple元组
开发语言·jvm·c++·python·程序人生·开源
CoderYanger1 小时前
A.每日一题:3622. 判断整除性
java·程序人生·算法·leetcode·面试·职场和发展·蓝桥杯
吴声子夜歌1 小时前
ApacheCommons——commons-lang3(Java 基础语言增强)(二)
java·开发语言·apache