消息丢失怎么办
可能出现消息丢失的三种情况:
- 生产者发送消息到RabbitMQ服务器后,RabbitMQ服务器出现宕机(生产者发送成功,mq宕机)
- RabbitMQ服务器出现类似脑裂问题后重启服务()
- 消费者接收到MQ消息后出现宕机或者业务处理异常(接收者接收到消息之后宕机/业务异常)
应对以上三种情况,有以下对应的解决方法:
生产者confirm模式
针对生产者发送消息后MQ宕机问题,生产者开启事务消息可以保证消息到达MQ服务器。经过测试开启事务消息会降低2~10倍的吞吐量,而且会使生产者和应用程序产生同步。
所以,RabbitMQ团队有更好的方案来保证消息投递:发送方确认模式。当然你需要告诉Rabbit将信道设置成confirm模式。
消息持久化
MQ服务器出现类似脑裂问题后重启服务器导致消息对视问题,如果MQ重启后,队列和交换机都会消失(随同里面的消息)。原因是因为每个队列和交换机默认的durable默认方式是false,确定了交换机和队列需要重新建立,我们将值设置为true就不会出现重新建立交换机和队列的情况,但是消息还是会消失。但是可以从奔溃的MQ中恢复的消息我们称为消息的持久化。只需将要投递的消息标记为持久化。RMQ的持久化,是不承诺100%消息不丢失的。
消息者补偿机制
MQ发送消息后消费者宕机或者消费者处理消息时出现异常的场景。消息丢失取决于消费者端是手动ack还是自动ack,如果业务量不大的情况可以使用手动ack,这样MQ就不会发送完消息之后马上删除消息,需要消费者确定消息处理完成之后才删除消息。如果业务量大的情况下使用手动ack会影响系统的吞吐量,可以出现消息积压现象。因此业务量大的话我们会选择自动ack,如何保证消息步丢失呢?
我们做了一下消息补偿机制:
其中的ES可以替换为其他非关系型数据库,MangoDB,Redis...
生产者发送消息
1.1 生产者发送消息到RabbitMQ服务器
1.2 RabbitMQ通过异步confirm方式通知生产者消息接收完成
1.3 生产者可以异步将消息存入ES(备份消息),防止MQ服务器重启导致消息丢失,当然交换机、队列和消息现在是持久化状态
消费者消费消息
2.1 消费者接收数据
2.2 接收到消息首先写入ES
2.3 业务处理完成后删除ES中备份的消息
补发定时任务
3 定时任务补发消费失败消息并更新补发次数
报警定时任务
4 定时任务抓取补发超过3次消息邮件报警人工干预