`
zengshaotao
  • 浏览: 786904 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

RabbitMQ如何解决被重复消费和数据丢失的问题

 
阅读更多

为什么要使用MQ?

1.解耦,系统A在代码中直接调用系统B和系统C的代码,如果将来D系统接入,系统A还需要修改代码,过于麻烦!

2.异步,将消息写入消息队列,非必要的业务逻辑以异步的方式运行,加快响应速度

3.削峰,并发量大的时候,所有的请求直接怼到数据库,造成数据库连接异常

使用了消息队列会有什么缺点?

1.系统可用性降低:你想啊,本来其他系统只要运行好好的,那你的系统就是正常的。现在你非要加个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性降低

2.系统复杂性增加:要多考虑很多方面的问题,比如一致性问题、如何保证消息不被重复消费,如何保证保证消息可靠传输。因此,需要考虑的东西更多,系统复杂性增大。

如何保证消息队列是高可用的?

使用集群的方式维持MQ的可高用性。

如何保证消息不被重复消费?

保证消息不被重复消费的关键是保证消息队列的幂等性,这个问题针对业务场景来答分以下几点:

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

2.再比如,你拿到这个消息做redis的set的操作,那就容易了,不用解决,因为你无论set几次结果都是一样的,set操作本来就算幂等操作。

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

如何解决丢数据的问题?

1.生产者丢数据

生产者的消息没有投递到MQ中怎么办?从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消息。

transaction机制就是说,发送消息前,开启事物(channel.txSelect()),然后发送消息,如果发送过程中出现什么异常,事物就会回滚(channel.txRollback()),如果发送成功则提交事物(channel.txCommit())。

然而缺点就是吞吐量下降了。因此,按照博主的经验,生产上用confirm模式的居多。一旦channel进入confirm模式,所有在该信道上面发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,rabbitMQ就会发送一个Ack给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了.如果rabiitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。

2.消息队列丢数据

处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。

那么如何持久化呢,这里顺便说一下吧,其实也很容易,就下面两步

①、将queue的持久化标识durable设置为true,则代表是一个持久的队列

②、发送消息的时候将deliveryMode=2

这样设置以后,rabbitMQ就算挂了,重启后也能恢复数据。在消息还没有持久化到硬盘时,可能服务已经死掉,这种情况可以通过引入mirrored-queue即镜像队列,但也不能保证消息百分百不丢失(整个集群都挂掉)

3.消费者丢数据

启用手动确认模式可以解决这个问题

①自动确认模式,消费者挂掉,待ack的消息回归到队列中。消费者抛出异常,消息会不断的被重发,直到处理成功。不会丢失消息,即便服务挂掉,没有处理完成的消息会重回队列,但是异常会让消息不断重试。

②手动确认模式,如果消费者来不及处理就死掉时,没有响应ack时会重复发送一条信息给其他消费者;如果监听程序处理异常了,且未对异常进行捕获,会一直重复接收消息,然后一直抛异常;如果对异常进行了捕获,但是没有在finally里ack,也会一直重复发送消息(重试机制)。

③不确认模式,acknowledge="none" 不使用确认机制,只要消息发送完成会立即在队列移除,无论客户端异常还是断开,只要发送完就移除,不会重发。

如何保证消息的顺序性?

针对这个问题,通过某种算法,将需要保持先后顺序的消息放到同一个消息队列中。然后只用一个消费者去消费该队列。同一个queue里的消息一定是顺序消息的。我的观点是保证入队有序就行,出队以后的顺序交给消费者自己去保证,没有固定套路。例如B消息的业务应该保证在A消息后业务后执行,那么我们保证A消息先进queueA,B消息后进queueB就可以了。



作者:架构师springboot
链接:https://www.jianshu.com/p/5ade5bf0dcd9
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
分享到:
评论

相关推荐

    javaAPI SpringMVC 集成rabbitMQ 实现了生产消费,重复消费等功能

    本文将深入探讨如何使用Java API和SpringMVC来集成RabbitMQ,实现消息的生产和消费,以及处理重复消费的问题。 1. **RabbitMQ基础**: - RabbitMQ是一个分布式消息中间件,它允许应用之间通过异步通信进行解耦,...

    springCloud-rabbitmq分布事物实现.zip

    在分布式系统中,确保数据的一致性和完整性是至关重要的,而Spring Cloud和RabbitMQ的结合可以帮助我们实现这一目标。本实例将详细讲解如何利用RabbitMQ解决分布式事务,通过基于Spring Cloud搭建的示例来阐述相关...

    RabbitMQ面试专题及答案.pdf

    RabbitMQ使用TCP信道来传输数据,这可以有效地解决TCP连接创建和销毁的开销问题,同时克服了系统资源限制对并发数的影响。在消息分发方面,RabbitMQ通过路由将消息发送至一个或多个队列,具体采用的交换器类型主要有...

    RabbitMQ笔记.pdf

    RabbitMQ的优势在于其开源性质,性能优秀,支持跨平台和跨语言数据生成与消费。它提供了可靠性消息投递模式、返回模式,并且与Spring AMQP完美整合。RabbitMQ支持集群模式、表达式配置、高可用(HA)模式和镜像队列...

    RabbitMQ相关问题总结.docx

    RabbitMQ 相关的问题,涵盖了为什么使用 RabbitMQ、使用 RabbitMQ 的场景、如何确保消息正确地发送至 RabbitMQ、如何避免消息重复投递或重复消费、消息基于什么传输、消息如何分发、消息怎么路由、如何确保消息不...

    rabbitMQ点对点发送消息

    为了解决这个问题,RabbitMQ引入了“点对点”(Point-to-Point)模型,也称为队列模型,它基于发布/订阅(Publish/Subscribe)的概念,但具有消息持久化的特性。 点对点模型的关键在于消息队列:当发送方发送一条...

    RabbitMQ Server3.13.0

    1. **Work Queues**: 用于负载均衡,多个消费者可以从同一个队列中获取任务进行处理,防止同一任务被重复处理。 2. **Publish/Subscribe**: 通过主题交换机实现广播模式,所有订阅特定主题的消费者都会收到消息。 ...

    RabbitMQ服务开发指南(修订版-1)

    4. **消息幂等性**:确保消息重复消费不会导致错误,例如使用唯一标识符和幂等操作。 5. **合理设置消息过期时间**:避免queue堆积过多消息,造成资源浪费。 以上是对RabbitMQ服务开发的基本介绍,包括其核心概念、...

    Release_rabbitmq_C#源码_

    8. **消息确认机制**:RabbitMQ提供了消息确认机制,允许消费者确认已处理的消息,确保消息不被重复处理或丢失。在C#客户端中,可以通过启用`AutoAck`模式或手动调用`BasicAck`方法来实现。 9. **消息队列的设计...

    RabbitMQ面试专题及答案1

    为了确保消息不丢失,可以启用消息和队列的持久化,RabbitMQ 在消息写入磁盘后才确认,服务器重启后能恢复未消费的消息。 使用 RabbitMQ 带来的益处包括: 1. **服务解耦**:增强系统的灵活性和可扩展性。 2. **高...

    rabbitmq面试题.pdf

    如何诊断和解决RabbitMQ的消息问题?** - 利用日志和监控工具定位问题原因。 - 优化消息处理逻辑和配置参数。 **45. 如果RabbitMQ的节点宕机,如何恢复?** - 通过故障转移机制自动切换到其他可用节点。 - 手动...

    rabbitmq-server-3.8.9.exe

    - **合理设计消息模式**:根据业务场景选择合适的消息模式,避免数据丢失或重复消费。 - **队列大小限制**:设置队列长度限制以防止内存溢出,同时确保及时处理消息。 - **负载均衡与高可用**:通过镜像队列或...

    java面试题_消息中间件--RabbitMQ(22题).pdf

    7、如何避免消息重复投递或重复消费? 8、消息基于什么传输? 9、消息如何分发? 10、消息怎么路由? 11、如何确保消息不丢失? 12、使⽤RabbitMQ有什么好处? 13、消息队列有什么缺点? 14、MQ如何选型? 15、如何...

    rabbitMQ-demo

    **RabbitMQ 深入理解与实战应用** RabbitMQ 是一个开源的消息代理和队列服务器,它基于 ...在实际操作中,要注意消息的幂等性设计,避免因重复消费导致的问题,同时考虑如何正确处理未确认消息,以确保系统的健壮性。

    RabbitMQ封装为c++版本,并且使用方式为发布订阅模式

    - 设计接口,使得生产者和消费者的行为可以被抽象和扩展。 - 错误处理和异常处理是必不可少的,确保在出现错误时能够优雅地处理。 封装后的C++库可以作为模块在不同的项目中重复使用,简化了RabbitMQ的集成工作,...

    重复消费、顺序消费、分布式事务.pdf

    综上所述,重复消费、顺序消费和分布式事务都是在消息队列和分布式系统中非常重要的概念和技术,对于构建高性能、高可靠性的系统至关重要。在实际应用中,需要结合具体场景选择合适的技术方案来解决这些问题。

    Springboot+RabbitMQ 消息中间件

    同时,合理设计消息的幂等性,避免因重复消费导致的问题。 总结来说,SpringBoot与RabbitMQ的整合提供了高效的消息处理能力。通过消息中间件,我们可以实现服务间的异步通信,提高系统的响应速度和容错性。结合...

    Dubbo+Solr+RabbitMQ实现Solr数据同步 DataSyncParent.zip

    2. **可靠传输**:RabbitMQ提供消息确认机制,确保消息不会丢失或重复。 3. **异步处理**:数据同步过程可以通过消息队列异步处理,避免阻塞主业务流程,提高系统响应速度。 在“Dubbo+Solr+RabbitMQ实现Solr数据...

    RabbitMQ实战 高效部署分布式消息队列pdf

    **RabbitMQ实战:高效部署分布式消息队列** 在当今的IT行业中,分布式系统和微服务架构变得...在实际项目中,结合具体的业务需求,灵活运用RabbitMQ的各种特性,可以解决很多复杂的问题,实现高效的通信和数据处理。

    RabbitMQ实战:高效部署分布式消息队列 带目录书签高清PDF

    1. 可靠性:通过确认机制(publisher confirms和consumer acknowledges)确保消息的可靠传递,避免数据丢失。 2. 路由与过滤:通过交换器和绑定规则,可以根据消息属性或路由键灵活地将消息路由到目标队列。 3. 幂...

Global site tag (gtag.js) - Google Analytics