顺序消息的异常与重试机制

顺序消息的异常与重试机制
顺序消息的重试和并发消息有很大不同异常处理情况 处理方式消费失败业务异常 返回 SUSPEND_CURRENT_QUEUE_A_MOMENT暂停当前 Queue 的消费等待重试重试次数 ≤ 最大重试次数 消息被重新投递再次消费重试次数 最大重试次数 投递到死信队列DLQ不再消费是否是否消费消息消费成功✅ 返回 SUCCESS继续下一条返回 SUSPEND_CURRENT_QUEUE_A_MOMENT暂停该 Queue 消费进入等待默认 1 秒重新投递该消息重试次数≤ 最大重试次数投递到死信队列跳过该消息继续后续消息顺序消息重试的关键特点阻塞后续消息一条消息消费失败该 Queue 后面的消息都会被阻塞直到这条消息被成功消费或进入 DLQ影响吞吐量因为阻塞机制顺序消息的吞吐量对单条消息的处理时间非常敏感最大重试次数默认 10 次并发消费默认 16 次可通过 consumer.setMaxReconsumeTimes() 调整顺序消息与并发消息的性能对比对比维度 并发消息 顺序消息线程模型 多线程并行 每个 Queue 单线程吞吐量 高充分利用 CPU 中受限于单线程串行延迟 低 中高单条失败会阻塞后续适用场景 大多数业务 需要严格顺序的场景推荐 Queue 数 Consumer 数量的 2-3 倍 尽量多提高并行度顺序消息吞吐量Queue 0单线程 中吞吐Queue 1单线程Queue 2单线程单条消息处理慢了整个 Queue 被拖慢并发消息吞吐量Queue 0线程池 高吞吐Queue 1Queue 2Queue 3性能差距量化在相同硬件条件下并发消息的 TPS 通常比顺序消息高 3-5 倍顺序消息中单条消息的处理时间直接影响整个 Queue 的吞吐量顺序消息的常见踩坑与规避踩坑 后果 规避措施使用默认的轮询队列选择器 相同业务 Key 的消息落到不同 Queue顺序被打乱 必须使用 MessageQueueSelector按 Key 哈希选 QueueConsumer 数量超过 Queue 数量 部分 Consumer 空闲浪费资源 Consumer 数 ≤ Queue 数建议 Consumer 数 Queue 数单条消息处理时间过长 整个 Queue 被阻塞吞吐量骤降 优化业务逻辑尽量缩短单条消息的处理时间如果必须长耗时考虑拆分或异步化消费异常返回 RECONSUME_LATER 阻塞后续消息影响效率 谨慎使用重试尽可能在业务层解决异常避免依赖重试Rebalance 频繁触发 顺序可能被短暂打断消息重复 稳定 Consumer 实例避免频繁上下线使用 AllocateMessageQueueAveragely 策略将顺序消息和并发消息混在同一 Group Rebalance 混乱顺序无法保证 分离 Group顺序消息使用独立的 Group解决方案常见踩坑❌ 队列选择器用错→ 顺序乱❌ Consumer Queue→ 资源浪费❌ 单条消息耗时过长→ 整体阻塞❌ 频繁 Rebalance→ 顺序中断✅ 用 MessageQueueSelector按 Key 哈希✅ Consumer 数 ≤ Queue 数✅ 优化业务逻辑异步化长任务✅ 稳定实例合理配置 Rebalance 参数十、延迟消息与定时消息延迟消息的概念与业务场景延迟消息是生产者发送消息时指定一个延迟时间消息在到达该时间后才被 Consumer 消费。它和普通消息的区别在于消息不是立即投递而是“预约”投递。典型业务场景场景 延迟时间 说明订单超时自动取消 30 分钟 下单后 30 分钟未支付自动取消订单定时提醒 1 天 预约明天上午 10 点的提醒重试调度 1s, 5s, 10s… 消费失败后延迟重试RocketMQ 内部已实现定时任务调度 固定时间 每天凌晨 2 点执行数据统计RocketMQ 延迟消息的等级机制18 个等级在 RocketMQ 4.x 及 5.x 早期版本中延迟消息基于预定义等级实现不支持任意时间延迟等级 1 2 3 4 5 6 7 8 9延迟 1s 5s 10s 30s 1m 2m 3m 4m 5m等级 10 11 12 13 14 15 16 17 18延迟 6m 7m 8m 9m 10m 20m 30m 1h 2h发送延迟消息Message msg new Message(“order_topic”, “订单内容”.getBytes());// 设置延迟等级为 3表示延迟 10 秒msg.setDelayTimeLevel(3);producer.send(msg);为什么使用等级机制内部通过 SCHEDULE_TOPIC_XXXX 的 18 个 Queue 来分别存储不同延迟等级的消息后台定时任务 ScheduleMessageService 扫描这些 Queue到时间后重新投递等级机制实现简单性能好但不够灵活延迟消息的存储与调度原理消费阶段调度阶段索引构建发送阶段设置 delayTimeLevel3写入ReputMessageService根据延迟等级定时扫描到达投递时间ProducerBrokerCommitLogConsumeQueueSCHEDULE_TOPIC_XXXXQueue 3ScheduleMessageService每个等级一个定时线程重新写入目标 Topic目标 Topic 的 ConsumeQueueConsumer 消费核心调度逻辑ScheduleMessageService 为每个延迟等级启动一个定时线程定时线程每隔固定时间默认 1 秒扫描对应的 Queue检查 ConsumeQueue 中的消息如果当前时间 ≥ 投递时间则从 CommitLog 中读取完整消息清除延迟属性重新写入目标 Topic 的 CommitLog 和 ConsumeQueue这样 Consumer 就能正常消费到这条消息延迟消息的消息重投与消费延迟消息的消费重试和普通消息完全一样基于 %RETRY% 重试队列。但有一个特殊点重试不会重置延迟。即消息第一次被消费失败后进入重试队列的重试延迟是独立的由重试队列的延迟等级决定和消息本身的延迟等级无关。

最新新闻

日新闻

周新闻

月新闻