RabbitMQ如何保证消息不丢失

RabbitMQ一般情况下消息不会发生丢失的问题,但是不能排除意外,为了保证我们自己的系统高可用,我们必须做出更好完善的措施,保证系统的稳定性。

1、消息持久化

RabbitMQ的消息默认放在内存上面,如果不特别声明设置,消息不会持久化到磁盘上,如果节点重启或者宕机,就会导致消息丢失。

(1)Exchange持久化:channel.exchangeDeclare(exchangeName, “direct/topic/header/fanout”, true);即在声明的时候讲durable字段设置为true即可。

(2)Quque持久化:queue的持久化是通过durable=true来实现的。

(3)Message消息持久化:发送消息设置发送模式deliveryMode=2,代表持久化消息。

2、ACK确认机制(异步)

多个消费者同时收消息,比如消息收到一半的时候,一个消费者死掉了(逻辑复杂事件太长,超时了或者消费被停机或者网络断开连接),如何保证消息不丢失?

使用Message acknowledgment机制,消费者消费完成要通知服务端,服务端才把消息从内存删除。

例如:生产者发生消息丢失

//设置消息发送确认--回调 开关
connectionFactory.setPublisherConfims(true);

//同时启动一个监听(生产者监听确认):监听生产者是否消息发送成功。
template.setConfirmCallback(confirmCallback());

例如:消费者消息丢失

消费者获取到消息之后,没有来得及处理完毕,自己直接宕机了,因为消息这默认采用自动ack,此时RabbitMQ的自动ack机制会通知MQ Server这条消息已经处理好了,此时消息就丢了,并不是预期的。

采用手动ACK机制来解决这个问题,消费端处理完逻辑之后在通知MQ Server,这样消费者没处理完消息不会发送ack,如果在消费者拿到消息,没来得及处理的情况下自己挂了,此时MQ集群会自动感知到,它会自觉的重发消息给其他的消费者服务实例。

# 需要两步操作
1、消费者监听设置手动ack
this.channel.basicConsume(queue, false, consumerTag, this);

2、业务完成后手动ack
context.getChannel().basicAck(deliveryTag, false);

3、设置集群镜像模式

RabbitMQ三种部署模式:
(1)单节点模式:最简单的情况,节点挂了,消息就不能用了。
(2)普通模式:默认的集群模式,某个节点挂了,该节点上的消息不能用,有影响的业务瘫痪,值能等待节点恢复重启可用(消息持久化的);
(3)镜像模式:把需要的队列做成镜像队列,存在于多个节点,输入RabbitMQ的HA方案,

三种HA策略模式:

  • (1)同步所有的
  • (2)同步最多的N个机器
  • (3)只同步至符合指定名称的nodes

4、消息补偿机制

持久化的消息,保存到硬盘中,当前队列节点挂了,存储节点硬盘又坏了,消息丢失了,怎么办?

产线网络环境太复杂,所以不知数太多,消息补偿机制需要建立在消息要写入DB日志,发送日志,节后日志,两者的状态必须记录。
然后根据DB日志记录check消息发送消费是否成功,不成功,进行消息补偿措施,重新发送消息处理。

5、路由保障(解决交换机消息丢失的问题)

路由保障的出现就是为了解决路由信息不匹配的情况,当消息没有成功通过路由键路由到队列中时,那么消息就会发生丢失的情况,主要有两种方式失败通知备用交换机

(1)失败通知
这时候就需要有一个失败通知(mandatory+ReturnListener)

//路由失败通知
template.setMandatory(true);
//回调
template.setReturnListener(returnCallback());

(2)备用交换机
在路由的时候,有可能是路由键路由的范围不够广

所以在创建交换机的时候可以再创建一个其他路由键的交换机(比如Fanout广播式交换机),以此来确保消息可以路由到另一个队列中,从而保证消息不会丢失

6、生产者生产消息到RabbitMQ Server可靠性保证?

(1)AMQP协议提供的一个事务机制(用的比较少)

(2)发送方确认机制

首先生产者通过调用channel.confirmSelect方法将信道设置为confirm模式,一旦
信道进入confirm模式,所有在该信道上面发布的小都会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后,RabbitMQ就会发送一个确认给生产者(包含消息的唯一deliveryTag和multiple参数),这就使得生产者知晓消息已经正确到达了目的地了。

其中Confirm模式有三种方式实现

  • 串行confirm模式:生产者每发送一条消息后,调用waitForConfirms()方法,等待broker端confirm,如果服务器端返回false或者在超时时间内未返回,客户端进行消息重传。

  • 批量confirm模式:生产者每发送一批消息后,调用waitForConfirms()方法,等待broker端confirm。

  • 异步confirm模式:提供一个回调方法,broker confirm了一条或者多条消息后producer端会回调这个方法。

7、消息幂等性—防止消息的重复消费

产生原因:网络延迟传输中,消费者出现异常或者消费者延迟消费,会造成进行MQ重试补偿,在重试过程中,可能会造成重复消费。
面试题:MQ中消费者如何保证幂等性问题,不被重复消费

在这里插入图片描述


版权声明:本文为weixin_44324174原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。