消息队列面试题
消息队列面试题
消息队列基础
消息队列由哪些角色组成?
- 生产者(Producer):负责产生消息。
- 消费者(Consumer):负责消费消息
- 消息代理(Message Broker):负责存储消息和转发消息两件事情。其中,转发消息分为推送和拉取两种方式。
- 拉取(Pull),是指 Consumer 主动从 Message Broker 获取消息
- 推送(Push),是指 Message Broker主动将 Consumer 感兴趣的消息推送给 Consumer 。
消息队列使用场景
消息队列使用场景?为何使用消息队列?
消息队列是一种用于在应用程序和系统组件之间传递消息的通信机制。它是一种异步通信模式,其中发送方将消息发送到队列中,而接收方则从队列中获取消息并进行处理。消息队列具有广泛的使用场景,包括但不限于以下几个方面:
- 异步通信:消息队列允许发送方和接收方在时间上解耦。发送方可以将消息放入队列中,然后继续执行其他任务,而无需等待接收方的即时响应。接收方可以根据自身的处理能力和可用性从队列中提取消息并进行处理。这种异步通信模式非常适用于需要处理高并发或高负载的系统。
- 应用解耦:消息队列提供了一种松耦合的通信方式,使得不同的应用程序或系统组件可以独立地进行开发、部署和扩展。发送方和接收方不需要直接知道彼此的存在,它们只需要知道如何发送和接收消息即可。这种解耦可以提高系统的可维护性和灵活性。
- 峰值处理能力:消息队列可以帮助处理突发的请求或负载峰值。当系统在某个时间段内面临大量的请求时,可以将请求放入消息队列中,然后逐渐进行处理,以避免系统过载或崩溃。这种能力对于处理流量突发性增加的系统非常重要,例如电商促销活动、社交媒体热点等。
- 任务排队和分发:消息队列可以用作任务的排队和分发机制。当有多个工作者(Workers)可用时,发送方可以将任务放入队列中,工作者可以从队列中获取任务并进行处理。这种机制可以有效地管理任务的执行顺序、负载均衡和故障恢复。
- 日志处理:消息队列可以用于日志的收集和处理。应用程序可以将日志消息发送到队列中,然后后台处理程序可以消费这些消息并将日志存储到适当的位置,例如数据库、文件或日志分析系统。这种方式可以实现异步的、可靠的日志处理,并且不会对应用程序的性能产生显著影响。
应用解耦的优点?
如果不同系统都是直接调用,如果一个被依赖的系统发生变动,依赖这个系统的系统都要发生变动。
通过消息队列,系统间并不是直接相互依赖,而是通过消息队列来传递消息。
深入了解消息队列
消息队列有几种消息语义?
一共有3种:
- 消息至多被消费一次(At most once):消息可能会丢失,但绝不重传。
- 消息至少被消费一次(At least once):消息可以重传,但绝不丢失。
- 消息仅被消费一次(Exactly once):每一条消息只被传递一次。
消息队列中有哪些消息投递方式?它们分别有什么优缺点?
消息队列有push 推送和 pull拉取两种消息投递方式。
- push
- 优点,就是及时性。
- 缺点,就是受限于消费者的消费能力,可能造成消息的堆积,Broker 会不断给消费者发送不能处理的消息。
- pull
- 优点,就是主动权掌握在消费方,可以根据自己的消息速度进行消息拉取。
- 缺点,就是消费方不知道什么时候可以获取的最新的消息,会有消息延迟和忙等。
如何保证消息者消费消息的幂等性
如果要达到消费者的消费消息的幂等性,就需要每条消息保证被送达,并且仅被消费者消费一次。
- 首先,需要一个消息排重的唯一标识,标识由消息生产者生成。
- 然后,需要一个排重的存储器。比如关系数据库,增加一个排重表,使用消息编号作为唯一主键。
- 最后,在消费者消费消息之后,插入这条排重记录。
消息队列如何保证消息的有序性
保证消息的有序性包括①生产者的消息顺序发送和②消费者的消息顺序消费。 消息队列本身并不能直接保证消息的严格有序性,因为它通常是一个并发的系统,消息的处理是并行进行的。然而,可以采取一些策略和技术来实现有序性,具体取决于应用程序的需求和消息队列的实现方式。下面是几种常见的方法:
- 单一消费者:将消息队列配置为只有一个消费者消费消息。这样可以确保消息按照发送的顺序被处理,因为消费者一次只能处理一个消息。
- 分区顺序:将消息队列中的消息根据某个可排序的键(例如消息的ID或时间戳)进行分区,每个分区由一个独立的消费者处理。这样可以保证同一分区内的消息按照顺序进行处理,但不同分区之间的消息可能是无序的。
- 消息排序器:在消息队列之前引入一个消息排序器组件。该组件负责接收无序的消息并根据某个标识(例如消息的ID或时间戳)对它们进行排序,然后将有序的消息发送到消息队列中供消费者消费。
- 延迟处理:在消息队列中引入延迟机制,确保消息在一定的时间窗口内按照顺序进行处理。这可以通过设置消息的延迟时间或引入消息的优先级来实现。
生产者的消息顺序发送和消费者的消息顺序消费
要实现生产者的消息顺序发送和消费者的消息顺序消费,可以采用以下方法:
① 生产者的消息顺序发送:
- 单线程发送:在生产者端,使用单线程发送消息,确保消息按照产生的顺序发送到消息队列中。这样可以保证消息的顺序性,但可能会降低发送的吞吐量。
- 消息缓冲区:在生产者端引入消息缓冲区,将产生的消息先放入缓冲区中。然后,按照顺序从缓冲区取出消息发送到消息队列中。这样可以避免发送过程中的并发问题,确保消息的有序发送。
② 消费者的消息顺序消费:
- 单一消费者:将消息队列配置为只有一个消费者消费消息。这样可以确保消息按照顺序被一个消费者处理,从而实现有序消费。
- 消费者协调:如果有多个消费者,并且需要保证消息的顺序消费,可以引入协调机制。例如,可以使用共享的锁或分布式锁来保证只有一个消费者能够同时处理消息,其他消费者需要等待。这样可以确保消息的有序消费,但可能会对系统的并发能力产生影响。
消息队列的消息存储方式
存储主要有两种:
- 将消息存储至文件系统。比如RabbitMQ、RabbitMQ、Kafka。
- 将消息存储至数据库。比如ActiveMQ。