RabbitMQ消息丢失以及解决策略

mac2025-04-02  3

1、消息丢失

1.1、RabbitMQ流程

producer——》RabbitMQ——》consumer SO:发生消息丢失的三种情况:

producer端:发送消息过程中出现网络问题:producer以为发送成功,但RabbitMQ server没有收到;RabbitMQ server 端:接收到消息后由于服务器宕机或其他原因(消息默认存在内存中)导致消息丢失;Consumer端:Consumer端接收到消息后处理消息出错,没有完成消息的处理;

1.2、producer端

解决方式:

事务:在生产者发送数据之前开启rabbitmq事务(channel.txSelect),然后发送消息,如果消息没有成功被rabbitmq接收到,那么生产者会收到异常报错,此时就可以回滚事务(channel.txRollback),然后重试发送消息;如果收到了消息,那么可以提交事务(channel.txCommit)。 缺点:耗费性能,效率低。 回执确认:开启confirm模式,在生产者那里设置开启confirm模式之后,你每次写的消息都会分配一个唯一的id,然后如果写入了rabbitmq中,rabbitmq会给你回传一个ack消息,告诉你说这个消息ok了。如果rabbitmq没能处理这个消息,会回调你一个nack接口,告诉你这个消息接收失败,你可以重试。而且你可以结合这个机制自己在内存里维护每个消息id的状态,如果超过一定时间还没接收到这个消息的回调,那么你可以重发。 区别: 事务是同步的,会发生阻塞; confirm是异步的,效率更高;

1.3、RabbitMQ Server端

解决方式:

消息持久化 RabbitMQ 的消息默认存放在内存上面,如果不特别声明设置,消息不会持久化保存到硬盘上面的,如果节点重启或者意外crash掉,消息就会丢失。

要想做到消息持久化,必须满足以下三个条件,缺一不可。

Exchange 设置持久化:durable:trueQueue 设置持久化:durable:trueMessage持久化发送:发送消息设置发送模式deliveryMode=2,代表持久化消息

1.4、Consumer端

解决方法:

ACK确认机制: 多个消费者同时收取消息,比如消息接收到一半的时候,一个消费者死掉了(逻辑复杂时间太长,超时了或者消费被停机或者网络断开链接),如何保证消息不丢? 这个使用就要使用Message acknowledgment 机制,就是消费端消费完成要通知服务端,服务端才把消息从内存删除。 这样就解决了,及时一个消费者出了问题,没有同步消息给服务端,还有其他的消费端去消费,保证了消息不丢的case。 具体步骤: 交换机调用basicQos(1)方法:告诉RabbitMQ 不采用以前那种实现分配好的模式进行消息推送,而是每次只推送一条。调用basicAck()方法手动回复ack消息调用basicconsume()方法时将第二个参数写为false(开启手动ACK)mq收到ack消息会删除当前的消息。没收到会等待一段时间然后将重新发送该消息。

消息重复

原因
消费者端在消费完成后,手动ack发出,但是由于网络原因mqServer没有收到。so mq保留此条消息而后被重复消费。生产者端发送消息,mqServer收到消息返回回执确认同样因为网络等原因生产者端并没有收到。再次发送同一条消息。
消息乱序

比如说生产者发送了两条消息:消息一:添加一条数据;消息二:修改这条数据;然而mq收到消息后发给消费者的顺序是不能保证的。有可能消费者先收到消息二;

so 如何解决呢? 很简单:将这种带有先后顺序的消息发送到同一个队列中,这样它的顺序是肯定的。
最新回复(0)