【MQ】面试题

MQ应用场景?

这一部分可以根据自己的实际使用场景进行分析。

比如:订单模块下单功能:支付成功后,给用户发送短信,就采取了MQ的方式。

这样达到了应用解耦(把订单模块与短信拆分)、异步处理(采用并行执行的方式,可以减少响应时间)。

除此之外,还可以在秒杀中使用MQ,进行流量削峰

假设秒杀系统每秒最多可以处理2k个请求,每秒却有5k的请求过来,可以引入消息队列,秒杀系统每秒从消息队列拉2k请求处理得了。

解决秒杀出现消息积压的问题,

  • 首先秒杀活动不会每时每刻都那么多请求过来,高峰期过去后,积压的请求可以慢慢处理;

  • 其次,如果消息队列长度超过最大数量,可以直接抛弃用户请求或跳转到错误页面;

消息队列技术选型?1

在这里插入图片描述
在4.5的版本中,RocketMQ有一个集群模式叫做:Dleger模式。当主节点失活时,能够自动重新触发选举。

MQ如何保证消息不重复消费?确保幂等性?

幂等处理重复消息:

  1. 表,带唯一业务标记的,利用主键或者唯一性索引,每次处理业务,先校验一下就好啦;
  2. mysql 插⼊业务id作为主键,主键是唯⼀的,所以⼀次只能插⼊⼀条
  3. 用redis缓存下业务标记,每次看下是否处理过了。
  4. 分布式锁来进行处理

MQ如何保证消息的可靠发送?

相关:如何保证数据一致性,事务消息如何实现?

消息的发送是从 生产者 -> MQ -> 消费者。所以,就从这三个方面去考虑。

生产者:确保消息能够发送到MQ里面。

RabbitMQ
生产者同步在发送消息后,开启MQ里面的消息回执(ConfirmCallback)。如果MQ接收到了消息,会发送一个布尔类型的ack。如果为true,表示消息已经被MQ进行接受。

RocketMQ
之前的版本,在同步模式中,发送失败后可以重试,设置重试次数。默认3次。
producer.setRetryTimesWhenSendFailed(10);
在 4.3之后的版本,增加了事务消息去确保生产方的可靠发送。采用了2PC,即两阶段提交,prepared->commit / rollback。
我们一般是重写了事务监听器类。生产方绑定这个事务监听器,在发送消息后,此时事务消息处于prepared状态,在这个状态中,对消费方是不可见的。事务监听器判断了事务消息的状态后,对消息修改为 Commit 或 Rollback。Commit 就是直接发送给消费者,Rollback就会再去在时间段内再去check消息状态。在一定次数的check以后,会把消息丢弃。


MQ :确保消息已经持久化到磁盘中。
在这里插入图片描述

刷盘机制分同步刷盘和异步刷盘;

  • 生产者消息发过来时,只有持久化到磁盘,RocketMQ的存储端Broker才返回一个成功的ACK响应,这就是同步刷盘。它保证消息不丢失,但是影响了性能。
  • 异步刷盘的话,只要消息写入PageCache缓存,就返回一个成功的ACK响应。这样提高了MQ的性能,但是如果这时候机器断电了,就会丢失消息。

Broker一般是集群部署的,有master主节点和slave从节点。消息到Broker存储端,只有主节点和从节点都写入成功,才反馈成功的ack给生产者。这就是同步复制,它保证了消息不丢失,但是降低了系统的吞吐量。与之对应的就是异步复制,只要消息写入主节点成功,就返回成功的ack,它速度快,但是会有性能问题。


消费

RabbitMQ
消息消费时,出现异常,就把消息使用死信队列进行处理。如果死信处理的时候出现异常,就人为进行处理。
RocketMQ
在消费者分组中,让一个消费者没有消息消费成功标识返回,那么就会发送给消费者组中的其他消费者。


从这里看出,MQ并不能做到100%的消息可靠。因此,如商品购买模块为例子,核心的流程(购买,支付)放到一个微服务,这样方便出现异常时事务回滚;用户购买之后,给用户发个短信(短信)就可以使用MQ进行处理。

MQ如何保证消息的顺序性?

RabbitMQ是不支持顺序消息的!
在这里插入图片描述
如图所示,RabbitMQ保证消息的顺序性,就是拆分多个 queue,每个 queue 对应一个 consumer(消费者),就是多一些 queue 而已,确实是麻烦点;或者就一个 queue 但是对应一个 consumer,然后这个 consumer 内部用内存队列做排队,然后分发给底层不同的 worker 来处理。2

RocketMQ
局部顺序:消费方消费MessageQueue里面的消息肯定是一致的。
在这里插入图片描述
全局顺序:一个broker只有一个MessageQueue,消息的消费肯定是顺序的。
在这里插入图片描述

MQ的消息积压问题

这个问题大概会从两个层面影响:

  1. 代码层面的问题:是不是有bug产生
  2. 实际上的业务场景:业务生产者正常生产消息大于消费者消费消息
  • 优化一下消费的逻辑,比如之前是一条一条消息消费处理的话,我们可以确认是不是可以优为批量处理消息。
  • 考虑水平扩容,增加Topic的队列数,和消费组机器的数量,提升整体消费能力。
  • 如果是突发的情况:可以采取临时扩容:
  1. 先修复consumer消费者的问题,以确保其恢复消费速度,然后将现有consumer 都停掉。
  2. 新建一个 topic,partition 是原来的 10 倍,临时建立好原先10倍的queue 数量。
  3. 然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。
  4. 接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数据。
  5. 等快速消费完积压数据之后,得恢复原先部署的架构,重新用原先的 consumer 机器来消费消息。1

消息死信的原因

RabbitMQ
消息被拒(Basic.Reject /Basic.Nack) 且 requeue = false。
消息TTL过期。
队列满了,无法再添加。

RocketMQ
消息消费失败到达一定次数(默认为16次)后,则进入了死信队列中。

如果让你写一个消息队列,该如何进行架构设计


  1. RocketMq常见面试题: https://blog.csdn.net/qq_42877546/article/details/125425061

  1. 《消息队列经典十连问》,原文链接:https://juejin.cn/post/70673222605115228230 ↩︎ ↩︎

  2. 《RabbitMQ系列(六)如何保证消息的顺序性、消息不丢失、不被重复消费》,原文链接:https://blog.csdn.net/weixin_45498465/article/details/105708875 ↩︎

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,下面是MQ(消息队列)面试中经常会遇到的6个经典问题: 1. 什么是消息队列(MQ)? 消息队列是一种常用的中间件技术,用于在不同的应用程序之间传递消息。它将消息发送到队列中,然后接收者从队列中接收消息,实现了应用程序之间的解耦。 2. MQ的优点是什么? MQ具有以下几个优点: - 异步通信:发送方发送消息后即可继续处理其他任务,接收方可以在合适的时候处理消息。 - 解耦合:发送方和接收方之间通过消息队列进行通信,彼此不需要直接知道对方的存在,实现了解耦合。 - 削峰填谷:可以通过消息队列平滑处理系统的峰值流量,保证系统的稳定性。 - 可靠性:消息队列通常具备高可靠性和持久化特性,可以确保消息不丢失。 3. RabbitMQ和Kafka有什么区别? RabbitMQ和Kafka是两种常见的消息队列系统,它们有以下区别: - RabbitMQ是一个传统的消息队列系统,采用AMQP协议,支持多种消息模式。适用于实时性要求较高、强一致性的场景。 - Kafka是一个高吞吐量、分布式的日志处理平台,采用发布-订阅模式。适用于大数据量、高并发的场景。 4. 如何保证MQ的高可用性? 保证MQ高可用性的方法主要有以下几种: - 集群部署:通过在多个节点上部署MQ实例,实现故障转移和负载均衡。 - 数据复制:将数据进行复制到多个节点上,确保数据的备份和容灾能力。 - 心跳机制:定期发送心跳检测消息,检测MQ节点的可用性。 - 监控和报警:监控MQ集群的运行状态,及时发现并解决问题。 5. 如何确保MQ的消息不丢失? 确保MQ消息不丢失的方法主要有以下几种: - 持久化:将消息存储到磁盘上,即使MQ节点宕机也能够恢复。 - ACK机制:发送方在发送消息后等待接收方的确认消息(ACK),确保消息被正确接收。 - 消息重试:当发送方发送消息失败时,可以进行重试操作,直到成功为止。 6. 如何保证MQ的顺序性? 保证MQ消息顺序性的方法主要有以下几种: - 单一消费者:每个队列只有一个消费者,确保消息按照顺序被处理。 - 分区顺序:将消息按照某个字段进行分区,同一分区内的消息按顺序处理。 - 消费者缓存:消费者接收到消息后缓存起来,按照顺序处理。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值