复盘女朋友面试4个月的RocketMQ面试题

简介: 这篇文章复盘了面试中关于RocketMQ的高频题目,包括架构组成、使用姿势、功能原理及高级特性,并强调了理解这些实现机制对于面试成功的重要性。

又来了,这是复盘第六波女朋友面试4个月的面试题,本次是关于RocketMQ的专题

在分布式系统中,消息队列是一个使用场景非常丰富的技术。我们通常会用来作为异步通信,系统解耦,海量请求或者数据的削峰填谷,也可能使用延迟消息或者顺序消息完成特殊场景的业务功能。

消息队列产品有Kafka,RocketMQ, rabbitmq, 是市面上使用比较多的一个中间件, 也是Java后端面试中命中率较高的专题。

还是老套路,高频的面试题已经标星,有面试需要的同学可以先点星星收藏起来

image.png

image.png

架构相关题目

  • 说说RocketMQ架构组成有哪些?

哈哈,这个题目是不是就是传说中的送分题?我们如果使用过RocketMQ一般都可以回答出这个答案。

RocketMQ由生产者,消费者,broker,nameserver四个组件组成。前面三者都会和nameserver通信,nameserver可以理解成注册中心,他会存储所有生产者,消费者,broker的信息。broker是支持高可用的,他支持集群和主从模式。我们脑海里如果记住有下面这幅图就能解答这个问题了。

7691B76D-3970-448D-ACA3-802461CCB7D9.png

rocketMQ官网也有这部分的这部分更加详细的介绍。认识RocketMQ

使用姿势

  • 在集群消费模式下,16个消费者,8个写队列,有什么问题?

回答这个问题,需要知道Rocketmq负载均衡机制,默认使用平均分配策略,并且一个消费者最小消费的单元是队列。所以如果消费者数量比队列数大的时候,大于队列的消费者是无法消费到消息的,下面是RocketMQ官网给出的图:

image.png

因此,我们一定要合理规划topic下的队列数量。

功能原理相关题目

  • 顺序消息原理

这个问题需要从生产者和消费者,broker三端来解答,因为顺序消息需要三端配合。

  1. 生产者

生产者发送消息时候需要根据自己的业务规则,实现MessageQueueSelector接口的select方法,计算当前消息路由到哪个队列去。


//队列负载均衡
public interface MessageQueueSelector {
   
   
    MessageQueue select(final List<MessageQueue> mqs, final Message msg, final Object arg);
}
//发送消息
SendResult sendResult = producer.send(msg, new MessageQueueSelector() {
   
   
                    @Override
                    public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
   
   
                        //arg 业务id
                        Integer id = (Integer) arg;
                        //生成订单 , 支付订单 保持顺序
                        System.out.println("订单id:"+id);
                        int index = id % mqs.size();
                        return mqs.get(index);
                    }
                }, orderId);
  1. 消费者

消费端消费的时候,consumer首先会向broker申请加锁,发送topic,queueId,clientId给broker,broker只会让这个消费者拉取对应队列的消息。

for (MessageQueue mq : mqs) {
   
   

if (this.isLocked(group, mq, clientId)) {
   
   
    lockedMqs.add(mq);
} else {
   
   
    notLockedMqs.add(mq);
}
}

真正消费的地方,consumer还会加锁。

先对MessageQueue加锁

public Object fetchLockObject(final MessageQueue mq) {
   
   
        Object objLock = this.mqLockTable.get(mq);
        if (null == objLock) {
   
   
            objLock = new Object();
            Object prevLock = this.mqLockTable.putIfAbsent(mq, objLock);
            if (prevLock != null) {
   
   
                objLock = prevLock;
            }
        }

        return objLock;
    }

真正处理消息前对processQueue加锁,保证当前消息队列Queue只被1个线程处理

try {
   
   
      //对处理队列加锁
      this.processQueue.getLockConsume().lock();
      //调用业务逻辑处理消息
      status = messageListener.consumeMessage(Collections.unmodifiableList(msgs), context);
  } catch (Throwable e) {
   
   
      hasException = true;
  } finally {
   
   
      //处理队列解锁
      this.processQueue.getLockConsume().unlock();
  }

顺序消息的实现是比较复杂的,因为涉及到锁和线程并发控制,源码需要多读几次才能理解。面试时我们要注重讲解核心要点。

  • 事务消息原理

生产者发送事务消息(这是半消息,无法被消费者消费的)之后,开始执行本地事务,根据本地事务执行情况,告诉broker本地事务结果,要么成功,要么失败,如果是成功,那么broker会将事务消息还原到真实的topic和队列,如果是失败,broker会将事务消息(半消息)删除。

这里如果生产者没有告诉broker本地事务的执行结果,broker有一个兜底的定时任务,broker启用一个线程,扫描事务消息topic里的队列里面的消息,判断是否需要检查事务状态(最大检查15次)。

面试的时候回答还是要简洁一些,首先要把主流程讲解出来,其实这个细节原理在RocketMQ的实现内部也是比较复杂的。

高级特性

  • RocketMQ为什么这么快?

这个问题好像似曾相识,因为很多时候面试官喜欢问一些归类总结性的问题,这个问题就是这样,可以判断候选者对技术有没有自己分析总结的能力,这种题目其实没有标准答案,需要了解技术实现的情况下,进行分析总结。

我们还是需要从生产者,消费者,broker来分析

首先是生产者,生产者发送消息支持同步,支持异步,还支持oneway,oneway效率最高,因为他不用等broker返回。

在broker端,消息由索引和消息内容数据两部分组成,消息内容先需要写到commitlog,先写到pagecache,再刷新到磁盘,由于commitlog是顺序写的,而刷盘支持异步刷,这样性能是极高的。

如果是消费者从broker拉取消息, 先查询索引数据consumerQueue,这些索引数据占用空间小,通过页缓存读取,并且本地有缓存机制,读取性能也非常高,读取文件使用到零拷贝mmap技术提高性能,而且消费者和broker保持长轮训机制,使新消息到达可以快速投递到消费端。

最后在消费者这边支持并发多线程消费,将topic和队列信息会进行本地缓存,同时和broker保持长链接,能够保证及时接收到最新的消息。

总结

RocketMQ专题的知识其实很多,底层涉及的一些技术,比如rpc通信,编码解码,零拷贝,刷盘机制,主从复制,负载均衡算法等是大部分中间件通用的一些技术点,如果问这个专题的面试题,有很多题可能被问到。因此我们需要掌握实现机制,才能从容面对面试官的灵魂发问。

如果大家对其他专题的面试题感兴趣,可以关注我的高频面试题专栏,里面已经有5个高频面试专题,后续会陆续更新成体系,成专题的面试题。

相关实践学习
消息队列RocketMQ版:基础消息收发功能体验
本实验场景介绍消息队列RocketMQ版的基础消息收发功能,涵盖实例创建、Topic、Group资源创建以及消息收发体验等基础功能模块。
消息队列 MNS 入门课程
1、消息队列MNS简介 本节课介绍消息队列的MNS的基础概念 2、消息队列MNS特性 本节课介绍消息队列的MNS的主要特性 3、MNS的最佳实践及场景应用 本节课介绍消息队列的MNS的最佳实践及场景应用案例 4、手把手系列:消息队列MNS实操讲 本节课介绍消息队列的MNS的实际操作演示 5、动手实验:基于MNS,0基础轻松构建 Web Client 本节课带您一起基于MNS,0基础轻松构建 Web Client
相关文章
|
5月前
|
消息中间件 存储 负载均衡
RocketMQ 面试题及答案整理,最新面试题
RocketMQ 面试题及答案整理,最新面试题
396 4
|
5月前
|
消息中间件 存储 监控
|
5月前
|
消息中间件 存储 监控
RabbitMQ 面试题及答案整理,最新面试题
RabbitMQ 面试题及答案整理,最新面试题
208 1
|
5月前
|
消息中间件 缓存 NoSQL
RabbitMQ 总结面试
RabbitMQ 总结面试
50 0
|
5月前
|
消息中间件 负载均衡 监控
【面试问题】RabbitMQ 的集群
【1月更文挑战第27天】【面试问题】RabbitMQ 的集群
|
5月前
|
消息中间件 分布式计算 监控
Python面试:消息队列(RabbitMQ、Kafka)基础知识与应用
【4月更文挑战第18天】本文探讨了Python面试中RabbitMQ与Kafka的常见问题和易错点,包括两者的基础概念、特性对比、Python客户端使用、消息队列应用场景及消息可靠性保证。重点讲解了消息丢失与重复的避免策略,并提供了实战代码示例,帮助读者提升在分布式系统中使用消息队列的能力。
170 2
|
5天前
|
消息中间件 存储 canal
阿里面试:canal+MQ,会有乱序的问题吗?
本文详细探讨了在阿里面试中常见的问题——“canal+MQ,会有乱序的问题吗?”以及如何保证RocketMQ消息有序。文章首先介绍了消息有序的基本概念,包括全局有序和局部有序,并分析了RocketMQ中实现消息有序的方法。接着,针对canal+MQ的场景,讨论了如何通过配置`canal.mq.partitionsNum`和`canal.mq.partitionHash`来保证数据同步的有序性。最后,提供了多个与MQ相关的面试题及解决方案,帮助读者更好地准备面试,提升技术水平。
阿里面试:canal+MQ,会有乱序的问题吗?
|
2月前
|
存储 缓存 网络协议
复盘女朋友面试4个月的Java基础题
这篇文章是关于Java基础面试题的复盘,涵盖了HashMap原理、对象序列化作用等高频面试问题,并强调了Java基础知识的重要性。
复盘女朋友面试4个月的Java基础题
|
2月前
|
SQL 存储 关系型数据库
复盘女朋友面试4个月的Mysql面试题(1万字)
该文章详细分析了Ribbon的超时配置是否会覆盖OpenFeign的超时配置,并探讨了OpenFeign超时配置能否动态实时修改生效的问题。
复盘女朋友面试4个月的Mysql面试题(1万字)
|
2月前
|
存储 缓存 Java
复盘女朋友面试4个月的Spring面试题
该文章复盘了关于 Spring 的面试题,包括 Spring 的好处、Bean 的生命周期、Spring 循环依赖的解决方法、AOP 的原理以及 Spring Boot 自动装配的原理等,强调对 Spring 核心原理的清晰理解对于回答面试题的重要性。
复盘女朋友面试4个月的Spring面试题