RabbitMQ(四)重复消费/幂等性和有序性

本文探讨了如何在RabbitMQ中处理消息重复消费问题,通过保证消息唯一性和幂等性,以及实现有序性,确保数据库操作正确性。涉及去重策略、数据库操作(如主键冲突)和使用第三方介质如Redis来维护消费记录。
摘要由CSDN通过智能技术生成

幂等性

首先,rabbitMQ并没有为消息的重复消费而设计一种解决方法,这个解决方法需要我们来根据业务自己实现,我整理了几种常见的解决方法。

消息重复发送导致消息被重复消费的场景

  1. 在生产者发送消息给rabbitMQ服务器的时候,有可能因为网络波动等情况,导致生产者收不到rabbitMQ服务器的应答,导致生产者再发送一条消息。

  2. 也是因为网络波动等问题,导致rabbitMQ服务器在向消费者发送消息的时候,没有收到消费者的应答,重复向消费者发生消息。

这两个场景,其实最终都是导致消费者重复消费多次消息,所以在一般的场景下,我们只需要在消费者那里做消息重复消费的保障即可。

解决方法

思路

保证消息的唯一性,就算是多次传输,不要让消息的多次消费带来影响;保证消息等幂性;

  • 在消息生产时,MQ内部针对每条生产者发送的消息生成一个inner-msg-id,作为去重和幂等的依据(消息投递失败并重传),避免重复的消息进入队列;
  • 在消息消费时,要求消息体中必须要有一个bizId(对于同一业务全局唯一,如支付ID、订单ID、帖子ID等)作为去重和幂等的依据,避免同一条消息被重复消费。

这个问题针对业务场景来答分以下几点:

  1. 如果消息是做数据库的insert操作,给这个消息做一个唯一主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。

  2. 如果消息是做redis的set的操作,不用解决,因为无论set几次结果都是一样的,set操作本来就算幂等操作。

  3. 如果以上两种情况还不行,可以准备一个第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将<id,message>以K-V形式写入redis。那消费者开始消费前,先去redis中查询有没消费记录即可。

有序性

如何保证消息的顺序性?

数据中台服务器A发送 创建学生信息 与 更新学生信息 两条消息。应用服务器B需要接受服务A的消息。接收到创建学生信息的消息就在表里创建一个学生记录。接受到更新学生的消息就更新学生基本信息。

如果B服务器部署了两台,服务A在很短的时间内发送了两条消息,那么服务B可能有一台做创建学生的操作,另外一台做更新学生的操作。那么就有可能发生,更新学生基本信息的操作早于创建学生基本信息的操作。这样的话更新就会失败。

这就牵扯到如何保证消息的顺序性

解决思路

在生产端发送消息的时候,把自己上一条消息ID 记录到放到消息体中。 在消费端接收到消息后,首先检查此消息中的 上一条消息ID属性。如果不存在上一条消息ID属性,那么就正常消费操作。如果成功消费,则将此次消费的消息ID记录到数据库中。  如果存在上一条消息ID属性,那么就先去数据库查看上一条消息是否已经成功被消费。 如果成功被消费,那么就执行正常的业务逻辑。消费并记录本次消息ID。  如果发现上一条消息没有被成功消费,那么可以稍等一下,在程序中执行睡眠X秒的操作。当休眠时间到了以后,再去检查一下上一条消息是否已经被成功消费。如果此时上一条消息仍然没有成功消费,那么就抛出异常,将当前的消息推回原队列,并等待下次重新消费。

在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值