RabbitMQ之消息的可靠性

1、场景导入

众所周知,Rabbit MQ是一款用Erlang语言编写的,基于AMQP协议的消息中间件。那么消息传输的可靠性就至关重要了,说到这里,我们先看一下Rabbit MQ的整个工作流程:
在这里插入图片描述
从上面一张图中,可以很容易知道,消息是由生产者发出,流经Broker(信道->交换机->队列),再到消费者消费完毕,这就是一个消息的完整流转过程。那么在这个过程中一定会出现消息传输不可靠问题,毕竟事无绝对嘛,但是魔高一尺道高一丈,Rabbit MQ早就为这些不可靠问题制定了相应的策略,下面就来看看消息传输的过程中有哪些不可靠的问题吧。

1.1、生产者消息丢失问题

比如生产者在发送消息的时候,因为网络问题,比如网络丢包、网络故障导致消失丢失。

1.2、Rabbit MQ服务器消息丢失问题:
  • Rabbit MQ服务器重启?
  • 集群模式下某一个节点服务宕机了?
1.3、消费者消息丢失问题:

消费者在拿到消息后,还没有将消息处理完成,就出现了宕机的情况,然而此时Rabbit MQ服务器却认为你已经消费了此条消息,这样就出现了消费者消息丢失问题了。

2、Rabbit MQ保证消息的可靠性

2.1、解决生产者消息丢失问题
2.1.1、事务机制

Rabbit MQ提供了消息的事务机制,在发送消息之前开启事务(channel.txSelect()),然后开始发送消息,如果消息发送失败或者发生异常,Rabbit MQ会进行事务回滚操作,如果发送成功了,则直接提交事务(channel.txCommit),这样虽然能保证消息不丢失。

但是事务机制有一个缺点,因为是同步操作,所以一条消息发送失败时会导致生产者端阻塞,直到收到Rabbit MQ的响应后,生产者才能继续发送消息,这样会导致生产者生产消息的吞吐量和性能会降低很多。

2.1.2、发送方确认机制(confirm模式)

confirm模式下,所有进入信道的消息都会被指定一个唯一的ID,一旦消息进入到匹配的队列后,RabbitMQ会发送一个确认标志和消息的唯一ID给生产者,这就使得生产者知道消息已经正确到达目的队列了;如果rabbitMQ没有处理该消息,则会发送一个未确认消息给你,你可以进行重试操作。这样也保证了消息不会丢失。

Confirm有三种实现方式:

  • 串行模式
  • 批量confirm模式
  • 异步confirm模式:提供一个回调方法,broker confirm了一条或者多条消息后producer端会回调这个方法。
2.2、解决Rabbit MQ服务器消息丢失问题:
2.2.1、Rabbit MQ服务器重启

正常情况下消息都是存储在内存中的,一旦服务器重启,那么内存中的消息是不是就都丢失了。那么要使消息不丢失,就得将消息放在一个地方保存下来,这样即使服务器重启,下次还能在保存的地方找到对应的消息,这样消息就不会丢失了。将消息保存下来的过程称之为消息的持久化。因为消息是存储在队列当中的,如果队列都没有了,那么消息肯定也就没有了,所以还得将队列也进行持久化,这样才能保证消息被持久性的保存下来。当然也可以选择将交换机也进行持久化,这个根据需要进行选择。

队列的持久化:

    /**
     * 设置持久化队列
     *
     * @return 返回队列
     */
    @Bean
    public Queue durableQueue() {
        //第一个参数是名字,第二个参数是代表是否持久化
        return new Queue(IMMEDIATE_QUEUE, true);
    }

消息的持久化

       //消息持久化
        Message message = MessageBuilder.withBody("消失持久化".getBytes()).build();
        message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
2.2.2、集群模式下某一个节点服务宕机了

集群模式下,一个节点服务器出现宕机的情况,那么就意味着这个节点所有的消息暂时是不可用的,那么面对这样一种情况,可以考虑有一台备用服务器,这个备用服务器要同步前面一台服务器的所有消息,这样在一个节点宕机之后,迅速连上备用节点服务器,这样可解决业务瘫痪的问题。Rabbit MQ服务器将这种集群模式称之为镜像集群模式,镜像模式至少采用3个节点,2个磁盘节点和1个内存节点。结构图如下所示:
在这里插入图片描述
镜像集群的一些策略:

扫描二维码关注公众号,回复: 10142572 查看本文章
  • 同步所有的节点
  • 最多同步N个节点
  • 只同步至符合指定名称的节点
2.3、解决消费者消息丢失问题:

消费者消息丢失问题是指消费者在拿到消息后,不管有没有将消息处理完成,就自动给RabbitMQ服务器返回消息确认结果了,这样就导致了RabbitMQ服务器没有接收到消费者真正处理完成的结果,这是由于消费者采用的是自动确认配置,就是不需要等待消息处理完成,只要消费者拿到消息后就自动给RabbitMQ服务器返回确认结果:该消息已确认消费了。

因此只需要将消费者的自动确认配置改为手动确认配置就解决问题啦,这样每次就需要等待消息处理完成后,消费者手动将确认结果返回给RabbitMQ服务器,如果中途消费者宕机了,那么就不会给RabbitMQ服务器返回确认信息了,RabbitMQ服务器就会将此条消息转发给其它匹配的消费者,这样就解决了消失丢失问题。

如侵权,请告知,立删!

欢迎各位关注我的JAVAERS公众号,陪你一起学习,一起成长,一起分享JAVA路上的诗和远方。在公众号里面都是JAVA这个世界的朋友,公众号每天会有技术类文章,面经干货,也有进阶架构的电子书籍,如Spring实战、SpringBoot实战、高性能MySQL、深入理解JVM、RabbitMQ实战、Redis设计与实现等等一些高质量书籍,关注公众号即可领取哦。
在这里插入图片描述

发布了10 篇原创文章 · 获赞 74 · 访问量 4373

猜你喜欢

转载自blog.csdn.net/qq_36526036/article/details/105083762