面试官:如何解决消息队列数据丢失问题?
面试官心理剖析:
生产上肯定会出现数据丢失问题,面试官主要是想看看你是否了解?有没有做过相应的措施来解决这个问题?如果你不知道有这个问题,那么你生产环境可能存在数据丢失问题。如果你的 MQ 用在核心场景下,如订单,扣费等,那么数据是万万不能丢的。
回答:
为什么会出现数据丢失?
分析:
丢数据一般会有 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,无外乎也都是这些原因,只要在各自端进行一些配置就可以解决数据丢失问题。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于