【面试宝典】如何解决消息队列数据丢失问题?

  |   0 评论   |   3,588 浏览

面试官:如何解决消息队列数据丢失问题?

面试官心理剖析:
生产上肯定会出现数据丢失问题,面试官主要是想看看你是否了解?有没有做过相应的措施来解决这个问题?如果你不知道有这个问题,那么你生产环境可能存在数据丢失问题。如果你的MQ用在核心场景下,如订单,扣费等,那么数据是万万不能丢的。

回答:

为什么会出现数据丢失?
分析:
imagepng
丢数据一般会有3种情况:
1)生产者往MQ写数据丢失了
可能因为网络原因数据传输丢失。
2)MQ本身数据丢失了
数据放在内存中,MQ机器宕机了,那么内存中的数据丢失了。
3)消费者消费的时候丢失了
消费者接受到消息,马上给MQ返回已经接受到消息的回复,消费者接着处理逻辑,在处理过程中,消费者宕机了;下次重启的时候消费者会获取到下一条数据消费,这样数据就丢失了。

问题解决:
1、解决rabbitmq生产者丢数据

1)事务机制
在生产者发送消息的时候,加上事务,以下是伪代码:

channel.txSelect
try{
//发送消息 如果MQ接收失败会抛异常,那么对事务进行回滚
}catch(Exception e){
channel.txRollback
}
channel.txCommit

改方案完全保证发送消息时成功的,但是缺点是:使用了事务之后,消息变成同步了,影响吞吐量。比较耗性能。

2)confirm模式
在生产者开启confirm模式,每个消息分配唯一id;生产者发送完消息之后就不用管了,rabbitmq如果成功接收到消息,那么会调用生产者的ack(String messageId)方法;rabbitmq如果接收失败,那么会调用生产者nack(String messageId)方法,生产者根据情况判断是否要重试;

小结:一般情况下,使用confirm模式,性能、吞吐量都要比事务机制高。confirm是异步的,不会阻塞。

2、解决rabbitmq弄丢了数据

就是开启持久化,把内存中的数据刷到磁盘中。如果在写入磁盘的时候挂了,这样的话还是会有数据丢失,但是概率很小,你可以等数据持久化到磁盘,在通知生产者ack方法,如果没有持久化成功,生产者长时间没收到消息可以尝试在重试一次。

3、解决rabbitmq消费端弄丢了数据

在消费端这边,需要关闭autoAck,等自己处理完之后在发送ack给MQ。

其他的MQ,无外乎也都是这些原因,只要在各自端进行一些配置就可以解决数据丢失问题。

本文为博主原创文章,未经博主允许不得转载。

评论

发表评论