RabbitMQ发布订阅模式同一消费者多个实例如何防止重复消费?

微服务架构模式中,服务间的通信一般采用HTTP、RPC或者MQ(消息队列)。在这三种方案中,HTTP和RPC是一对一的方式,通常用来进行查询或者命令式的操作,MQ则多用于事件的发布和处理。

在实际项目中我们通常会遇到一种情况:

事件有多个订阅者,有的订阅者部署多个实例,要求每个事件只需要发布一次,每个订阅者都要能收到且仅能有其中一个实例收到并进行处理。

简单说就是既要所有订阅者都能收到消息,又要保证每个订阅者只能消费一次,不能重复消费。那么在使用RabbitMQ作为消息中间件时应该如何处理这个问题?

需求

微服务架构下使用RabbitMQ作为服务总线中间件,有这样一种场景,订单服务在用户提交订单后会发送OrderCreatedEvent事件,需要接收此事件的服务有以下几个:

1、日志服务(单点部署);

2、消息系统,给用户发送短信、邮件(单点部署);

3、仓储系统,接收通知备货,扣减库存等(多实例,有负载均衡),同一条消息仅允许一个实例消费;

4、财务系统,记录收入流水(多实例,有负载均衡),同一条消息仅允许一个实例消费;

5、BI系统,做销售统计等;

问题

OrderCreatedEvent发出后,5个服务均可以接收到消息并进行处理,但是仓储和财务部署了多个实例,也就意味着每个实例都能收到相同的消息,这种情况下如何避免重复消费?

方案

  1. OrderCreatedEvent事件建立一个fanout exchange
  2. 每个需要处理OrderCreatedEvent的订阅者单独建立一个queue,订阅者的所有实例都消费这一个queue的消息。
  3. 将所有OrderCreatedEvent订阅者的queue都bind到第一步建立的exchange上。
  4. 事件发布者将OrderCreatedEvent消息发布到exchange,由exchange将消息路由到对应的queue,最后由queue锁定一个消费者实例并进行投递。

以下是示意图

四种主要 Exchange 类型

RabbitMQ主要有四种核心的Exchange类型:Fanout(广播)、Direct(精确匹配)、Topic(模式匹配)和Headers(按头匹配),它们决定了消息如何从交换机路由到队列,其中Direct、Topic、Fanout最常用,而Headers和一些插件类型(如x-delayed-message)提供更灵活的路由功能。

  1. Fanout (扇出)

    • 特点:将消息广播到所有绑定到它的队列。
    • 路由规则:忽略路由键 (Routing Key)。
    • 场景:适用于日志系统、通知广播等需要消息分发到多个消费者的场景。
  2. Direct (直连)

    • 特点:消息根据与队列绑定的精确路由键来路由。
    • 路由规则消息的 Routing Key 必须完全 匹配 队列绑定的 Routing Key
    • 场景:一个消费者处理特定类型的任务,如处理"用户注册"消息。
  3. Topic (主题)

    • 特点 :使用通配符(* 匹配一个词,# 匹配零个或多个词)进行模式匹配路由。
    • 路由规则消息的 Routing Key 模式需要与 队列绑定的模式 匹配。
    • 场景 :日志级别过滤,如logs.info.* 匹配所有 info 级别的日志,logs.# 匹配所有日志.
  4. Headers (头部)

    • 特点:根据消息的 Headers 属性(键值对)进行路由,而不是 Routing Key。
    • 路由规则:匹配消息 Headers 中的键值对与绑定时设置的键值对。
    • 场景:当需要根据复杂属性匹配时,较少使用,因为性能不如前三者。

Demo

后面我将会提供以上方案的具体实现,包含Java.net两种版本。

相关推荐
阳光是sunny7 小时前
LangGraph中的Reducer是什么
前端·人工智能·后端
灯澜忆梦7 小时前
GO_并发编程---定时器
开发语言·后端·golang
阳光是sunny7 小时前
从链到图:LangGraph 入门基础全解析
前端·人工智能·后端
皮皮林5517 小时前
开源实力派,给本地 AI 装上深度调研能力,一张 3090 跑到 95.7 分!
后端
努力的小雨8 小时前
把 Windows 桌面图标做成一个会自己运转的小世界
后端
武子康8 小时前
Search Console Platform Properties 扩大 SEO 资产边界:从 Page Ranking 到 Topic Coverage(5 类误读边界 + 3 表数据层设计)
前端·人工智能·后端
腾渊信息科技公司9 小时前
Spring Boot对接MES实战:视觉检测数据自动同步方案
java·人工智能·spring boot·后端·计算机视觉·ai·软件需求
IT_陈寒10 小时前
Vue这个特性差点让我加班到凌晨,谁懂啊
前端·人工智能·后端
段一凡-华北理工大学10 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
码事漫谈11 小时前
1999年的电商前夜和2026年的AI前夜 历史押韵但从不重复
后端