前言
遇到 MQ 的面试问题,基本无法摆脱经常会遇到的几个问题:MQ 解决什么问题?如何保证可靠投递?如何保证消息一致性?等等问题,以下将重点分析面对一致性的问题,在面试时应该如何回答会更有优势。
本文主要总结下本人经常面试时候的回答方向,欢迎各位给出意见,互相学习。谢谢!
问题:为什么使用MQ
面试官:有没有用过 MQ?为什么会使用 MQ?
作为一名后端开发者如果不懂 MQ的话就说不过去了。基于此题的问答,基本都是想考察下你对 MQ 的了解。一般系统引入 MQ 消息中间件无非就是 2个目的:系统解耦和流量控制。它们都是为了解决高可用和高性能。
一般解答时都是回答其作用:解耦、削峰填谷。但我们最好是加入自己曾经参与过项目例子进一步解说。
比如,之前曾经参与过 XXX 项目,因为项目集成的功能太多,有时候因为系统宕机就会导致整个发送消息的流程也受到影响。所以增加了MQ 解耦系统,由专门的消费者进行消息投递和转发。或者因为有时候高峰期时,因为流量突增的场景,通过MQ 实现流量的削峰填谷的作用。
问题:如何保证消息不丢失
面试官:那在使用 MQ 消息队列时,如何保证消息不丢失?
首先要了解消息从生产者到消费者的过程:
-
生产者:生产消息,并将消息发送给 MQ
-
消息组件:消息存储在 MQ 中
-
消费者:从消息组件上拉取消息并消费
整个消息生产到被消费过程中,这三个阶段都可能会发生问题:在生产者端消息可能未正常产生,或没有投递到MQ 中;在消息组件过程中,节点宕机导致消息丢失,从而使得消费者没有拉取到消息;在消费者端可能服务宕机或者 bug 问题导致消息没有正常消费。
生产者,一般都是能够正常产生消息,除非存在 bug 问题导致没有产生消息。产生消息发送给消费者,这个过程可能会出现问题,所以如果消息组件接收到生产者发送的消息时返回一个 ack 响应给生产者,这样就可以保证消息不丢失。
消息组件,现有的中间件都有很强大的功能,多集群的功能,使用从节点作为副本,并支持主节点宕机后从节点升级为主节点。这样就可以完全放心不会丢失数据。
消费者,从消息组件上拉取消息,消费的时候可能发生异常导致消息没消费,但又从消息组件删除了消息。所以一定要让消费者消费完后在返回一个Ack 响应给消息组件,然后消息组件再删除其存储的消息。
从整个过程,看似天衣无缝的可以解决消息丢失的问题。但在分布式上可能还是会出现问题,所以尽量还是增加 check 机制:生产者生产消息后,并入库,消费者消费完后,再将消息标志为已消费。
总结
当然,还会很多关于 MQ 消息队列相关的面试问题。比如如何保证消息不被重复消费?如何处理消息积压问题。像此类问题自己心中要有一个 MQ 从生产者到消费者这样的一个流程,并在每个流程点要明白可能会发生的问题。
我觉得很重要的一点就是,结合自己的实践项目去解说过程,这样才能更有说服力。可能大家没有太多的经历,可以去研究一些比较熟悉的秒杀系统,或者自己造一个项目演练 MQ 的过程。
本文正在参加「金石计划 . 瓜分6万现金大奖」