一文搞懂消息队列面试常见问题

本文参考 传值播客消息队列面试题公开课 https://www.bilibili.com/video/BV1FE411A7AA?t=345

1、为什么要用消息队列?(消息队列的应用场景)

考察面试者是否知道为什么要用消息队列,消息队列在项目重解决什么问题。

rabbimq消息队列架构图
消息队列是一种“先进先出”的数据结构,

用处1:解耦
系统的耦合性越高,容错性就月底。以电商系统为例,用户创建订单后,如果耦合调用库存系统、物流系统、支付系统,任何一个子系统出了故障或者因为升级等原因暂时不可用,都会造成下单操作异常,影响用户使用体验。

在这里插入图片描述
用处2:异步
A系统接收一个请求,需要在自己本地写库,还需要在B、C、D三个系统写库,自己在本地写库要3ms,B、C、D三个系统分别写库要300ms、450ms、200ms。最终请求总延时是3 + 300 +450 + 200 = 953ms,接近1s,用户体验非常不好。一般互联网的企业,对于用户的直接操作,一般要求都在每个请求200ms以内完成,对用户几乎是无感知的,如果用户通过浏览器发起请求,等待1s,是不可接受的。

在这里插入图片描述
用处3:流量消峰
应用系统如果遇到系统请求流量的瞬间猛增,有可能会将系统压垮。有了消息队列可以将大量请求缓存起来,分散到一个很长时间处理,这样可以大大提高系统的稳定性和用户体验。
或者业务正常时段如果是1000,高峰时段会达到10000,为了节约成本,也可以引用MQ进行流量消峰。
在这里插入图片描述

2、各种消息队列产品的比较

特性 ActiveMQ RabbitMQ RocketMQ kafka
开发语言 java erlang java scala
单机吞吐量 万级 万级 10万级 10万级
时效性 ms级 us级 ms级 ms级以内
可用性 高(主从架构) 高(主从架构) 非常高(分布式架构) 非常高(分布式架构)
功能特性 成熟的产品,在很多公司得到应用;有较多的文档;各种协议支持较好 基于erlang开发,所以并发能力很强,性能极其好,延时很低;管理界面较丰富 MQ功能比较完备,扩展性佳 只支持主要的MQ功能,像一些消息查询,消息回溯等功能没有提供,毕竟是为大数据准备的,在大数据领域应用广。
  • ActiveMQ,早期使用比较多,没有经过大规模吞吐量场景的验证,社区也不是很活跃.不推荐使用
  • RabbitMQ,开发语言erlang阻止了大量Java工程师深入了解它,对公司而言,基本处于不可控状态.但RabbitMq是开源的,比较稳定,活跃度也较高,如不考虑二次开发,追求稳定性和可靠性的情况,推荐使用.
  • RocketMQ,开发语言是Java,在阿里内部经受过高并发业务的考验,稳定性和性能均不错,考虑后期可能二次开发,推荐使用.
  • Kafka,大数据领域的实时计算,日志采集等场景,是kafka业内标准的,社区活跃度很高,推荐使.大数据领域日志采集等业务推荐使用.

3、消息队列的优点和缺点

考察面试者在使用这种新技术时,是否考虑过该技术对项目所带来的优点和缺点,而不是只停留在机械的使用.

优点:

  • 解耦
  • 异步
  • 消峰

缺点:

  • 系统可用性降低:系统引入的外部依赖越来越多,系统稳定性越差,就会对业务造成影响。
  • 系统复杂度提高:MQ引入加大了系统的复杂度,系统由同步的远程调用,变成了通过MQ进行异步调用。
  • 一致性问题:A系统处理完业务,通过MQ给B、C、D三个系统发消息数据,如果B,C处理成功,D处理失败,就会造成一致性问题。可用分布式事务解决

4、如何保证消息队列的高可用

面试官想知道的是面试者针对可用性降低问题的思考和解决思路。

RabbitMQ高可用—普通集群

  1. 在多台机器上分别启动RabbitMQ实例。
  2. 多个实例之间可以相互通信。
  3. 创建的Queue只会放在一个RabbitMQ上,其它实例都同步元数据。
  4. 消费的时候,如果连接的没有Queue,那么当前实例会从queue所在实例拉取数据。

特点:没有做到真正的高可用并且数据拉取的开销和单实例的瓶颈问题

在这里插入图片描述
RabbitMQ高可用—镜像集群

  1. 在多态机器上分别启动RabbitMQ实例.
  2. 多个实例之间可以互相通信
  3. 每次生产者写消息到queue时,都会自动把消息同步到多个实例的queue上。每个RabbitMQ节点上都有queue的消息数据和元数据
  4. 某一个节点宕机,其它节点依然保持完整数据,不影响客户段消费。

5、如何保证消息的不丢失

是否清除消息丢失的原因、如何保证消息不丢失

消息丢失的原因:

  • 情况一:消息生产者没有成功发送到MQ
  • 情况二:消息发送给MQ,MQ宕机导致内存中消息丢失
  • 情况三:消费者消费了消息,但没有处理完毕就出现了异常导致丢失。

在这里插入图片描述
解决方案:

  • 生产者发送给MQ后,MQ给生产者确认收到
  • MQ收到消息后进行消息持久化
  • 消费者收到消息处理完毕后手动进行ack确认
  • MQ收到消费者ack确认后删除持久化消息

在这里插入图片描述

6、如何保证消息不被重复消费?(如何保证消息消费的幂等性)

考察对重复消费产生原因的思考,对保证幂等性的方案

根本原因是网络不可达

生产者消息重复 当一条消息发送到服务端后,出现了网络闪断,导致服务器对客户端应答失败。如果此时生产者意识到消息发送失败并尝试再次发送消息,消费者会后续收到两条相同的消息。
在这里插入图片描述
消费者消息重复 消息消费的场景下,消息已经投递到消费者并完成业务处理,当消费方给MQ反馈应答时网络闪断。导致MQ服务端再次投递已被处理过的相同消息。
在这里插入图片描述
保证消费幂等性解决方案:

  1. 消息发送者发送消息时携带一个全局唯一的消息id
  2. 消费者获取消费后先根据id在redis/db中查询是否存在消费信息
  3. 如果没有消费过就正常消费,消费完毕后写入redis
  4. 如果消息消费过就直接舍弃

7、如何保证消息消费的顺序性

考察是否理解什么是消息顺序消费以及是否思考过消息顺序消费的方案

消息有序指的是可以按照消息的发送顺序来消费
例如:一笔订单产生了3条消息,分别是订单创建、订单付款、订单完成,同时多笔订单可以并行消费。

解决方案:
在这里插入图片描述

  1. 生产者根据消息ID将同一组消息发送到一个Queue中。
  2. 多个消费者同时获取Queue中的消息进行消费
  3. MQ使用分段锁保证单个Queue中的有序消费

8、大量消息堆积处理怎么处理

9、消息过期怎么处理

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章