【RabbitMQ】保证消息的不重复消费

本文探讨了RabbitMQ中保证消息不重复消费的问题,分析了出现非幂等性的原因,包括生产者和消费者的场景。生产者通过MQ系统内部生成的全局唯一inner-msg-id确保消息发送的幂等性,而消费者则依赖业务ID进行判重以保证幂等消费。总结指出,实现幂等性需要MQ和业务上下游的共同配合。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、出现非幂等性原因

为保证消息的可达性,超时、重传、确认机制可能导致消息总线、或者业务方收到重复的消息,从而对业务产生影响。

  1. 可靠性投递机制:比如消息已经发送出去,mq已经收到了,然后mq在返回confirm的时候网络出现闪断,导致broker未收到应答,导致发送两次。
  2.  MQ Broker服务与消费端传输消息的过程中出现网络抖动
  3. 消费端故障、异常

二、生产者

MQ消息发送上半场,即上图中的1-3

1,发送端MQ-client将消息发给服务端MQ-server

2,服务端MQ-server将消息落地

3,服务端MQ-server回ACK给发送端MQ-client

如果3丢失,发送端MQ-client超时后会重发消息,可能导致服务端MQ-server收到重复消息。

 

此时重发是MQ-client发起的,消息的处理是MQ-server,为了避免步骤2落地重复的消息,对每条消息,MQ系统内部必须生成一个inner-msg-id,作为去重和幂等的依据,这个内部消息ID的特性是:

(1)全局唯一

(2)MQ生成,具备业务无关性,对消息发送方和消息接收方屏蔽

 

有了这个inner-msg-id,就能保证上半场重发,也只有1条消息落到MQ-server的DB中,实现上半场幂等。

 

### RabbitMQ 防止消息重复消费的最佳实践与机制 为了确保 RabbitMQ 会出现消息重复消费的情况,通常需要采取一系列措施来保障消息的幂等性和可靠性。以下是具体的实现方式: #### 1. **唯一标识符** 为每条消息分配一个全局唯一的标识符(如 UUID)。当消费者接收到消息时,在处理前检查此标识符是否已被记录。如果已存在,则说明该消息已经被处理过,可以直接忽略。 这种方法的核心在于维护一份已处理过的消息 ID 列表,可以通过缓存或者数据库存储这些标识符[^5]。 ```python import uuid def process_message(message_id, message_content): if is_message_processed(message_id): # 检查消息ID是否已处理 print(f"Message {message_id} already processed.") return try: # 执行实际业务逻辑 handle_business_logic(message_content) # 记录已处理的消息ID mark_message_as_processed(message_id) except Exception as e: print(f"Error processing message {message_id}: {e}") ``` #### 2. **状态检查** 在处理消息之前,验证当前系统的状态是否允许执行对应的操作。例如,假设某条消息用于更新订单状态,可以在处理前查询数据库中的订单状态,判断目标状态是否已经是预期值。如果是,则无需再次执行更新操作。 这种做法特别适用于涉及资源修改或状态变更的任务场景。 #### 3. **数据库唯一约束** 利用数据库的唯一性约束特性,防止相同数据被多次写入。例如,针对某些特定字段设置索引并启用唯一性校验,这样即便同一条消息被多次提交至系统,也只会保留第一次成功的记录。 示例 SQL 创建语句: ```sql CREATE TABLE order_updates ( id SERIAL PRIMARY KEY, order_id VARCHAR(255) NOT NULL UNIQUE, -- 使用UNIQUE关键字定义唯一键 status VARCHAR(50), updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); ``` #### 4. **幂等 API 设计** 设计支持幂等性的接口服务,使得客户端能够安全地重试失败请求而影响最终一致性。推荐采用 HTTP `PUT` 方法代替传统的 `POST` 请求完成资源更新类动作;因为前者天然具备覆盖现有实体的能力,从而减少了因网络波动等原因引发的数据冗余风险。 另外还可以考虑引入版本号参数控制每次调用的具体行为变化情况。 --- 以上四种方案各有优劣,可根据实际情况灵活选用一种或多组合起来共同作用于整个工作流当中以达到最优效果。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值