当前位置: 首页 > news >正文

Rabbitmq Direct Exchange(直连交换机)多个消费者,配置相同的key ,队列,可以保证只有一个消费者消费吗

思考

可以保证消费不被重复消费,因为通过轮询一个消息只会投递给一个消费者。

但是不是一个消费者消费,而是多个轮询消费


在 RabbitMQ 中,如果多个消费者(Consumers)同时订阅 同一个队列(Queue),并且这个队列是通过 Direct Exchange 绑定的(使用相同的 routing_key),那么默认情况下 不能保证只有一个消费者消费,而是会按照 轮询(Round-Robin) 的方式分发给多个消费者。


1. 默认行为(多个消费者订阅同一个队列)

场景描述

  • Direct Exchange 绑定了 1 个队列(Queue),并指定了 routing_key(如 payment.success)。

  • 多个消费者 同时订阅这个队列。

消息分发方式

✅ 轮询(Round-Robin)

  • RabbitMQ 会 依次 将消息分发给不同的消费者,不会保证唯一消费

  • 例如:

    • Consumer1 收到消息1、消息3、消息5...

    • Consumer2 收到消息2、消息4、消息6...

代码示例

python

# 生产者发送消息到 Direct Exchange
channel.basic_publish(exchange="direct_exchange",routing_key="payment.success",  # 匹配绑定的队列body="Order123 paid"
)# 多个消费者订阅同一个队列
channel.basic_consume(queue="payment_queue", on_message_callback=consumer1)
channel.basic_consume(queue="payment_queue", on_message_callback=consumer2)

结果:消息会被 consumer1 和 consumer2 轮流消费,而不是仅由一个消费者处理。


2. 如何确保只有一个消费者消费?

如果你希望 同一消息只被一个消费者处理,有以下几种方案:

方案 1:单队列 + 单消费者

  • 只启动 1 个消费者,其他消费者不订阅该队列。

  • 缺点:无法扩展,吞吐量低。

方案 2:RabbitMQ 单活跃消费者(Single Active Consumer)

  • RabbitMQ 3.8+ 支持 单活跃消费者 模式:

    python

    channel.queue_declare(queue="payment_queue",arguments={"x-single-active-consumer": True}  # 启用单活跃消费者
    )
  • 行为

    • 多个消费者可以注册,但 只有第一个注册的消费者能接收消息

    • 如果该消费者断开,RabbitMQ 会自动切换到下一个消费者。

  • 优点

    • 无需额外组件(如 Redis 锁)。

    • 自动故障转移。

  • 缺点

    • 仍然不能并行处理消息。

方案 3:业务幂等性(推荐)

  • 允许消息被多个消费者消费,但业务逻辑保证 重复消费不影响结果(如数据库唯一约束、乐观锁)。

  • 优点

    • 高可用,可扩展多个消费者。

  • 缺点

    • 业务逻辑需要支持幂等。

方案 4:分布式锁(Redis / DB 锁)

  • 消费者处理消息前先获取锁:

    python

    def callback(message):lock_key = f"lock:{message.body.order_id}"if redis.set(lock_key, "1", nx=True, ex=60):  # 加锁process_payment(message)redis.delete(lock_key)  # 释放锁else:channel.reject(message.delivery_tag, requeue=True)  # 重新入队
  • 优点

    • 严格保证唯一消费。

  • 缺点

    • 依赖外部存储(Redis/DB)。

    • 锁超时时间需合理设置。


3. 总结

方案适用场景是否严格唯一消费扩展性
单队列 + 单消费者低吞吐场景✅ 是❌ 差
单活跃消费者(RabbitMQ 3.8+)需要自动故障转移✅ 是❌ 差
业务幂等性高并发场景❌ 否(但业务层防重)✅ 好
分布式锁严格一致性✅ 是⚠️ 中等

推荐

  • 如果业务允许,优先采用 幂等性(方案 3)。

  • 如果需要严格单消费者,使用 单活跃消费者(方案 2)或 分布式锁(方案 4)。


关键结论

🚨 Direct Exchange + 相同 routing_key + 相同队列 + 多个消费者 = 消息轮询分发(不保证唯一消费)
如果业务需要 严格单消费者,必须额外控制(如单活跃消费者或分布式锁)

http://www.lryc.cn/news/591610.html

相关文章:

  • IAR编译后处理 并复制日期
  • QT跨平台应用程序开发框架(10)—— Qt窗口
  • 《每日AI-人工智能-编程日报》--2025年7月17日
  • 突破AI模型访问的“光标牢笼”:长上下文处理与智能环境隔离实战
  • 记录timesfm2.0复现及调优
  • Shell编程简介
  • 解决leetcode第3614题用特殊操作处理字符串II
  • DolphinScheduler 如何高效调度 AnalyticDB on Spark 作业?
  • Redis学习-02安装Redis(Ubuntu版本)、开启远程连接
  • leetcode 206.反转链表(c++详细解释)
  • LeetCode--48.旋转图像
  • ACOUSLIC-AI挑战报告:基于低收入国家盲扫超声数据的胎儿腹围测量|文献速递-医学影像算法文献分享
  • Leetcode 03 java
  • 记录Leetcode中的报错问题
  • Java数组补充v2
  • sqli-labs靶场通关笔记:第25-26a关 and、or、空格和注释符多重过滤
  • 融智兴科技: RFID超高频洗涤标签解析
  • 代码随想录算法训练营第二十三天
  • Java 中的类和对象
  • 数据结构自学Day9: 二叉树的遍历
  • Git简介与特点:从Linux到分布式版本控制的革命
  • redis中间件
  • git merge-base查看某个分支从哪里拉出来的、主main分支上的某个时间之后某人的提交合并到特定分支(使用 cherry-pick 的场景)
  • 【MySQL事务】事务的隔离级别
  • 逆向破解京东评论加密参数|Python动态Cookie解决方案
  • 开源Agent平台Dify源码剖析系列(五)核心模块core/agent之CotChatAgentRunner
  • 文字转图片的字符画生成工具
  • 今日行情明日机会——20250717
  • Web3.0 实战项目、简历打造、精准投递+面试准备
  • springboot 整合spring-kafka客户端:SASL_SSL+PLAINTEXT方式