RabbitMQ使用过程中常见的问题

文章目录

  • 一、RabbitMq如何保证消息不丢失?
    • 1.哪些消息环节有丢消息的可能
    • 2.MQ消息零丢失方案
  • 二、如何保证消息幂等
  • 三、如何保证消息顺序
  • 四、RabbitMQ的数据堆积问题
  • 五、RabbitMQ的备份与恢复

一、RabbitMq如何保证消息不丢失?

1.哪些消息环节有丢消息的可能

通用的MQ场景有4中:生产者产生消息到MQServer、主节点到从节点、MQServer到操作系统、消费者消费来自MQServer。其中生产者产生消息到MQServer、主节点到从节点、消费者消费来自MQServer这三个场景是跨网络,有消息丢失的可能。


2.MQ消息零丢失方案

1)生成者保证消息正确发送到RabbitMQ
对于单个数据,可以使用生产者确认机制。通过多次确认的方式,保证生产者的消息能够正确的发送到RabbitMQ。
RabbitMQ的生产者确认机制分为同步确认和异步确认。
同步确认:通过在生产者端使用Channel.waitForConfirmsOrDie()指定一个等待确认的完成时间。
异步确认:通过channel.addConfirmListener(ConfirmCallback var1,ConfirmCallback var2)在生产者端注入两个回调确认函数。第一个函数是在生产者发送消息时调用,第二个函数则是生产者收到Broker的消息确认请求时调用。两个函数需要通过sequenceNumber自行完成消息的前后对应。sequenceNumber的生成方式需要通过channel的序列获取:int sequenceNumber = channel.getNextPublishSeqNo();
在RabbitMQ中还可以通过手动事务的方式,保证消息的正确发送。
手动事务机制主要有几个关键的方法:channel.txSelect()开启事务,channel.txCommit()提交事务,channel.txRollback()回滚事务;(备注:手动控制事务逻辑,会对channel产生阻塞,造成吞吐量下降)

2)RabbitMQ消息存盘不丢消息
Classic经典队列将队列声明持久化队列
Quorum队列和Stream队列,本身是持久化队列
3)RabbitMQ主从消息同步不丢消息
普通集群模式,消息是分散存储的,不会主动进行消息同步,是有丢消息的可能。镜像模式集群,数据会在集群中的各个节点主动同步,丢消息的概率会比较低。启用Feredation联邦机制,给包含重要消息的队列建立一个远端备份。
4)RabbitMQ消费者不丢失消息
消费者消费消息时可以指定自动应答还是手动应答。
自动应答模式:消费者会在完成业务处理自动进行应答。如果消费者的业务逻辑抛出异常,RabbitMQ会将消息进行重试,虽然这样不会丢失消息,但会造成重复消费。
手动应答模式,可以提高消息消费的可靠性


二、如何保证消息幂等

RabbitMQ消息自动重试机制:当消费者消费消息处理业务逻辑时,如果抛出异常或者不向mq返回响应,默认情况下,RabbitMQ会无限次数的重复进行消息消费。
一般我们会设定RabbitMQ的重试次数,然后再业务上处理幂等问题,给每个消息一个唯一的标识。


三、如何保证消息顺序

方法:单队列+单消息推送。即一组有序的消息只发到一个队列中,利用队列的FIFO特性保证消息在队列内顺序不会乱。然后消费者进行消费时,保证只有一个消费者,同时指定prefetch属性为1,即RabbitMQ每次往客户端只推送一条消息。
RabbitMQ不支持多队列,消息消费顺序。


四、RabbitMQ的数据堆积问题

使用Quorum队列或者Stream队列
如果Classic队列出现消息堆积,需要从数据流转的各个环节综合考虑
在消息生产者端:降低消息生产的速度。可以采用批量消息的方式,降低IO频率。
在RabbitMQ服务端:可以预先添加懒加载机制,或者创建sharding分片队列,或者使用Stream队列
在消息消费者端:增加消费者数量


五、RabbitMQ的备份与恢复

RabbitMQ有一个data目录会保存分配到该节点上的所有消息。该目录分为两部分,一部分为元数据(定义结构的数据),另一部分是消息存储目录。
元数据:可以通过web管理页面用json文件直接导入或者导出
消息存储目录:首先要保证MQ拥有全部元数据(可以通过web管理页面用json文件导入),然后备份过程需要将应用停止,如果是集群,需要整个集群停止。最后复制内容到数据文件夹。


你可能感兴趣的:(java,rabbitmq,分布式,java)