计算机系统应用教程网站

网站首页 > 技术文章 正文

「干货」面试被问到如何保证RabbitMQ消息不丢失该怎么回答?

btikc 2024-10-17 08:45:27 技术文章 7 ℃ 0 评论

MySQL调优视频合集

zookeeper详解视频合集

微服务搭建视频合集

RabbitMQ特性

  • 异步
  • 解耦
  • 削峰填谷
  • 正是由于其存在以上特性,所以被广泛应用于实际开发中,但是线上环境却存在消息丢失的场景,需要我们通过一些技术手段来保证最终数据的一致性(即MQ消息不丢失),首先我们先需要了解下RabbitMQ整体的架构图如下:

    RabbitMQ组成

    通过上面架构图我们可以看到RabbitMQ大致分为3部分,

    1. 客户端(生产者)
    2. RabbitMQ消息中间件
    3. 服务端(消费者)

    RabbitMQ消息丢失原因

    那么究竟哪些环节会导致消息丢失呢?

    • 生产者发送消息到RabbitMQ服务器后,RabbitMQ服务器出现宕机
    • RabbitMQ服务器出现类似脑裂问题后重启服务
    • 消费者接收到MQ消息后出现宕机或者业务处理异常

    RabbitMQ消息丢失解决方案

    那么根据以上可能存在的问题,我们需要通过一些手段来保证消息不丢失。

    生产者confirm模式

    ? 首先针对生产者发送消息到RabbitMQ服务器后,RabbitMQ服务器出现宕机的情况,生产者在发送消息给RabbitMQ服务器时,事务消息可以保证消息发送到RabbitMQ服务器,事务的实现主要是对信道(Channel)的设置,主要的方法有三个:

    • channel.txSelect()声明启动事务
    • channel.txComment()提交事务
    • channel.txRollback()回滚事务

    但是以上事务会降低大约2~10倍的吞吐量,而且会使生产者和应用程序产生同步,而我们使用RabbitMQ通信的目的就是要避免同步。所以,RabbitMQ团队有更好的方案来保证消息投递:发送方确认模式。当然你需要告诉Rabbit将信道设置成confirm模式。Confirm的三种实现方式:

    • channel.waitForConfirms()普通发送方确认模式
    • channel.waitForConfirmsOrDie()批量确认模式
    • channel.addConfirmListener()异步监听发送方确认模式;

    消息持久化

    ? 接下来我们讨论如何解决RabbitMQ服务器出现类似脑裂问题后重启服务导致消息丢失的问题,如果RabbitMQ重启之后,那些队列和交换器就会都消失了(随同里面都消息)。原因是每个队列和交换器都durable默认为false,他决定了RabbitMQ重启或宕机后需要重新建立交换器和队列,那么当我们将durable属性设置为true后,交换器和队列是不会重建了,但是消息却还会消失,能从AMQP服务器崩溃中恢复的消息,我们称之为消息的的持久化。在发布消息前,通过把他的投递模式选项设置为2来把消息标记为持久化。Java中设置方式为channel.basicPublish("", QUEUE_NAME, MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes()); 但是消息持久化会带来性能问题,影响RabbitMQ的吞吐量,所以要适当取舍。但是这里要注意一点,RabbitMQ的消息持久化,是不承诺100%的消息不丢失的。

    消费者补偿消息

    ? 最后我们讨论消费者接收到MQ消息后出现宕机或者业务处理异常的情景应该如何处理,消费者消息丢失的主要原因是由于当消费者接收到RabbitMQ的消息后,是手动ack还是自动ack,如果业务量不大话可以使用手动ack的方式,这样的话RabbitMQ就不会盲目的投递消息到消费者后,立马就删除消息了,说白了就是不会自作主张的认为消息处理成功了,但是手动ack在业务量较大的情况下会影响系统的吞吐量,如果消费出现异常还有可能会导致消息积压,因此我们采取的是自动ack的方式,那么这样的话又如何保证消息不丢失呢?

    ?我们消息补偿的架构图如下:

    生产者发送消息

    1.1 生产者发送消息到RabbitMQ服务器

    1.2 RabbitMQ通过异步confirm方式通知生产者消息接收完成

    1.3 生产者可以异步将消息存入ES(备份消息),防止MQ服务器重启导致消息丢失,当然交换机、队列和消息现在是持久化状态

    消费者消费消息

    2.1 消费者接收数据

    2.2 接收到消息首先写入ES

    2.3 业务处理完成后删除ES中到消息

    补发定时任务

    3 定时任务补发消费失败消息并更新补发次数

    报警定时任务

    4 定时任务抓取补发超过3次消息钉钉报警人工干预

    不断分享开发过程用到的技术和面试经常被问到的问题,如果您也对IT技术比较感兴趣可以「关注」我

    本文暂时没有评论,来添加一个吧(●'◡'●)

    欢迎 发表评论:

    最近发表
    标签列表