RabbitMQ 消息顺序性保证

方式一:Consumer设置exclusive

注意条件

  • 作用于basic.consume

  • 不支持quorum queue

    当同时有A、B两个消费者调用basic.consume方法消费,并将exclusive设置为true时,第二个消费者会抛出异常:

    com.rabbitmq.client.AlreadyClosedException: channel is already closed due to channel error; protocol method: #method<channel.close>(reply-code=403, reply-text=ACCESS_REFUSED - queue 'test' in vhost '/' in exclusive use, class-id=60, method-id=20)
    at com.rabbitmq.client.impl.AMQChannel.ensureIsOpen(AMQChannel.java:190)
    at com.rabbitmq.client.impl.AMQChannel.rpc(AMQChannel.java:223)
    at com.rabbitmq.client.impl.ChannelN.basicConsume(ChannelN.java:981)
    at com.dms.rabbitmq.TopicSender.lambdamain2(TopicSender.java:63)
    at java.base/java.lang.Thread.run(Thread.java:840)

Spring AMQP 如何通过exclusive实现顺序消费:


核心逻辑

复制代码
while (!DirectMessageListenerContainer.this.started && isRunning()) {
   this.cancellationLock.reset();
   try {
      for (String queue : queueNames) {
         consumeFromQueue(queue);
      }
   }
   catch (AmqpConnectException | AmqpIOException e) {
      long nextBackOff = backOffExecution.nextBackOff();
      if (nextBackOff < 0 || e.getCause() instanceof AmqpApplicationContextClosedException) {
         DirectMessageListenerContainer.this.aborted = true;
         shutdown();
         this.logger.error("Failed to start container - fatal error or backOffs exhausted",
               e);
         this.taskScheduler.schedule(this::stop, Instant.now());
         break;
      }
      this.logger.error("Error creating consumer; retrying in " + nextBackOff, e);
      doShutdown();
      try {
         Thread.sleep(nextBackOff); // NOSONAR
      }
      catch (InterruptedException e1) {
         Thread.currentThread().interrupt();
      }
      continue; // initialization failed; try again having rested for backOff-interval
   }
   DirectMessageListenerContainer.this.started = true;
   DirectMessageListenerContainer.this.startedLatch.countDown();
}
  1. 抛出异常后,会重试
  2. 重试间隔、次数受recoveryInterval(默认无限)、recoveryBackOff控制

方式二:single active consumer

原理:

代码示例

复制代码
Channel ch = ...;
Map<String, Object> arguments = newHashMap<String, Object>();
arguments.put("x-single-active-consumer", true);
ch.queueDeclare("my-queue", false, false, false, arguments);

参考资料:https://www.rabbitmq.com/blog/2022/07/05/rabbitmq-3-11-feature-preview-single-active-consumer-for-streams

相关推荐
爱浦路 IPLOOK3 小时前
矿山无人化作业5G专网方案:企业专网核心网络选型分析
网络·分布式·科技·5g·信息与通信
实战派K8S&DB5 小时前
如何在内网配置 TiDB 数据库 Agent
数据库·人工智能·分布式·tidb
实战派K8S&DB5 小时前
《基于 Dify + FastAPI + PyTiDB 搭建大模型驱动的 TiDB 智能运维 Agent》
运维·数据库·分布式·云原生·tidb·fastapi
小白羊丨6 小时前
Kafka任务重试、退避与失败恢复怎么做?
分布式·kafka
jyOverQ11 小时前
RabbitMQ 延迟消息怎么实现?TTL 与死信队列
分布式·后端·rabbitmq·ruby
zcmodeltech13 小时前
工程车模型多车型动作控制系统设计与实现方案——基于STM32与Modbus RTU的挖掘机、装载机、自卸车、起重机、电力工程车全场景控制方案,服务范围覆盖全国
分布式·stm32·单片机·嵌入式硬件·交互
StevenSurpass16 小时前
智能工厂场景:FastPrintAgent 分布式打印中间件落地应用方案
分布式·mqtt·http·中间件·打印·fastreport
江畔柳前堤1 天前
具身智能全景深度指南(2026年9月版):从“会聊天的AI“到“能干活的机器“
大数据·javascript·图像处理·人工智能·分布式·智慧城市·原型模式
夕除1 天前
redis--010
笔记·分布式·学习
寻求出路的程序媛1 天前
分布式 & 高性能 & 高可用 体系、学习重点、面试点
分布式·后端·面试·性能优化