消息队列-如何保证消息的可靠性传输(如何处理消息丢失的问题)?

面试题

如何保证消息没有重复消费?或者说,如何处理消息丢失的问题?

考察缘由

这个是肯定的,用 MQ 有个基本原则,就是数据不能多一条,也不能少一条,不能多,就是前面说的重复消费和幂等性问题。不能少,就是说这数据别搞丢了。那这个问题你必须得考虑一下。

如果说你这个是用 MQ 来传递非常核心的消息,比如说计费、扣费的一些消息,那必须确保这个 MQ 传递过程中绝对不会把计费消息给弄丢

面试题剖析

一、消息丢失问题描述

生产者、消费者。生产者必须让mq收到消息,消费者必须能够接收到消息并且消费成功,这就是消息的可靠性。然而在传输过程中,数据的丢失问题,可能出现在生产者、MQ、消费者中。现以activeMQ来分析。

1.1.1、生产者弄丢了数据

生产者将数据发送到 ActiveMQ的时候,可能因为网络问题等原因,在生成的过程中数据丢失。

解决方案

        基于生成者发送消息自己不知道是否发送成功的情况,有如下两种解决方式。

        事务机制:可以选择用 activeMQ提供的事务功能,就是生产者发送数据之前开启 activeMQ事务。Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE); 但是问题来了,如果使用activeMQ事务机制(同步)一搞,基本上吞吐量会下来,因为太耗性能

          非事务机制(消息持久化,confirm 机制):事务机制和 confirm 机制最大的不同在于,事务机制是同步的,你提交一个事务之后会阻塞在那儿,但是 confirm 机制是异步的,你发送个消息之后就可以发送下一个消息,然后那个消息 RabbitMQ 接收了之后会异步回调你的一个接口通知你这个消息接收到了。

Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

producer.setDeliveryMode(factory.getDeliveryMode())

所以一般在生产者这块避免数据丢失,都是用 confirm 机制的。


1.1.2、ActiveMQ弄丢了数据

当生产者发送消息到ActiveMQ,Active没进行消失持久化时挂掉了,此时ActiveMQ重启的时候发送过来的数据就丢失了。解决方案是要将接收到的消息进行持久化操作。

producer.setDeliveryMode(DeliveryMode.PERSISTENT);

ActiveMQ不设置,默认就是持久的.

1.1.3、消费者弄丢了数据

        activeMQ如果丢失了数据,主要是因为你消费的时候,刚消费到,还没处理,结果进程挂了,比如重启了,那么就尴尬了,RabbitMQ 认为你都消费了,这数据就丢了。

        自动重试机制:自动确认,收到消息以后,自动应答并且消费成功了。 如果有异常不会自动应答,并且会重发6次。Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);


吞吐量:联想到机场吞吐量,表示的是一定时间飞机的起降架次和旅客的运输数量。在系统就表示一定时间内请求获得响应的数量,反应的是系统的处理性能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容