消息队列MQ面试题解,基础面试题

一、为什么使用MQ?MQ的优点

简答

  • 异步处理 - 相比于传统的串行、并行方式,提高了系统吞吐量。
  • 应用解耦 - 系统间通过消息通信,不用关心其他系统的处理。
  • 流量削锋 - 可以通过消息队列长度控制请求量;可以缓解短时间内的高并发请求。
  • 日志处理 - 解决大量日志传输。
  • 消息通讯 - 消息队列一般都内置了高效的通信机制,因此也可以用在纯的消息通讯。比如实现点对
  • 点消息队列,或者聊天室等。

详答

主要是:解耦、异步、削峰。

解耦:

A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C系统现在不需要了呢?A 系统负责人几乎崩溃...A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。

就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用是不需要直接同步调用接口的,如果用 MQ 给它异步化解耦。

异步:

A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要

3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求。如果使用MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms。

削峰:

减少高峰时期对服务器压力。

二、说说引入消息队列有什么优缺点?

优点上面已经说了,就是在特殊场景下有其对应的好处,解耦、异步、削峰

缺点有以下几个:

系统可用性降低

本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因此,系统可用性会降低;

系统复杂度提高

加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。

一致性问题

A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。

所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。

三、聊聊市面上各MQ的特点

ActiveMQ

ActiveMQ是老牌的消息中间件,国内很多公司过去运用的还是非常广泛的,功能很强大。

但是问题在于没法确认ActiveMQ可以支撑互联网公司的高并发、高负载以及高吞吐的复杂场景,在国内互联网公司落地较少。而且使用较多的是一些传统企业,用ActiveMQ做异步调用和系统解耦。

RabbitMQ

他的好处在于可以支撑高并发、高吞吐、性能很高,同时有非常完善便捷的后台管理界面可以使用。另外,他还支持集群化、高可用部署架构、消息高可靠支持,功能较为完善。而且经过调研,国内各大互联网公司落地大规模RabbitMQ集群支撑自身业务的case较多,国内各种中小型互联网公司使用RabbitMQ的实践也比较多。

除此之外,RabbitMQ的开源社区很活跃,较高频率的迭代版本,来修复发现的bug以及进行各种优化,因此综合考虑过后,公司采取了RabbitMQ。但是RabbitMQ也有一点缺陷,就是他自身是基于erlang语言开发的,所以导致较为难以分析里面的源码,也较难进行深层次的源码定制和改造,毕竟需要较为扎实的erlang语言功底才可以。

RocketMQ

是阿里开源的,经过阿里的生产环境的超高并发、高吞吐的考验,性能卓越,同时还支持分布式事务等特殊场景。而且RocketMQ是基于Java语言开发的,适合深入阅读源码,有需要可以站在源码层面解决线上生产问题,包括源码的二次开发和改造。

Kafka

Kafka提供的消息中间件的功能明显较少一些,相对上述几款MQ中间件要少很多。但是Kafka的优势在于专为超高吞吐量的实时日志采集、实时数据同步、实时数据计算等场景来设计。因此Kafka在大数据领域中配合实时计算技术(比如Spark Streaming、Storm、Flink)使用的较多。但

是在传统的MQ中间件使用场景中较少采用。

四、MQ消息堆积有遇到过吗

产生MQ消息堆积的原因

    1. 生产者投递消息的速率与我们消费者消费的速率完全不匹配。
    1. 生产者投递消息的速率>消费者消费的速率 导致我们消息会堆积在我们 mq 服务器端中,没有及时的被消费者消费 所以就会产生消息堆积的问题
    1. 注意的是:rabbitmq 消费者我们的消息消费如果成功的话 消息会被立即删除。 kafka 或者rocketmq 消息消费如果成功的话,消息是不会立即被删除。

解决办法

    1. 提高消费者消费的速率;(对我们的消费者实现集群)
    1. 消费者应该批量形式获取消息 减少网络传输的次数

五、MQ消息堆积有遇到过吗

为什么会出现重复消费?

MQ的消息流程主要有两个阶段来完成,发送消息到消息队列以及消息队列将消息投递到消费者,

因为各种网络原因会造成发送方与以及接收方消息重试,就会造成重复消费

发送方消息重试

因为网络原因以及MQ自身原因会导致发送的消息未成功投递到MQ,如果出现未成功投递就会重复投递消息,这个时候是正常的,但是可能因为网络原因导致消息确认消息延时,实际上已经投递到了MQ但是确认消息没有己实被发送方接收到,就会重新发起消息重试,这样就会造成消息重复,这种是发送方消息重试,但是发送方重试次数是有限制的,如果达到一定次数后还是失败如果没有做其他处理就会造成消息丢失。

消费方消息重试

当消息正常投递到MQ后,就需要消费消息了,正常情况下消息会被发送到消费方进行消费,消费方一般需要开启手动确认来确定消息一定会被消费掉,但是可能网络原因导致消息未被消费,这个时候消费方就会重试消费消息,如果是出现消费超时或者异常就会进行消息重复消费,如果异常没有处理好导致消息重复消费可能造成业务出现幂等性问题,但是如果做了幂等性问题,多次消费还是失败就会造成消息丢失。

如果出现重复消费如何解决

唯一主键

手动给每一条消息增加一个唯一的消息ID,使用消息ID作为唯一主键,如果消息重复,消息插入不进去,用这种方式来解决消息重复

使用幂等

使用幂等方式来解决重复消费问题,手动给每一条消息增加一个唯一的消息ID,不要使用系统生成的消息ID,如果生成消息后就将消息保存到Redis中,如果消息消费成功后删除Redis中的消息,如果失败了不需要管redis中的消息,这样就完来实现消息的幂等。

六、MQ如何保证消息的有序消费

什么是有序消费

一个queue,有多个consumer去消费,这样就会造成顺序的错误,consumer从MQ里面读取数据是有序的,但是每个consumer的执行时间是不固定的,无法保证先读到消息的consumer一定先完成操作,这样就会出现消息并没有按照顺序执行,造成数据顺序错误,并且执行的时候是多线程执行的,并不能保证执行的顺序性。

有序消费的实践落地

单队列顺序

  • 生产者:将消息按照顺序发送到同一个队列。
  • 消费者:单线程或一个消费实例按消息进入队列的顺序逐条消费。

多队列分区顺序

通过分区或分组机制,让同一分区内的消息保持有序。(Kafka、RocketMQ)

生产者:

  • 根据消息的业务属性(如订单 ID、用户 ID 等),计算出哈希值或分区键。
  • 将相同分区键的消息发送到同一个队列或分区。

消费者:

  • 每个分区对应一个固定的消费实例,按顺序拉取消息。
  • 在消息消费完毕后,逐步处理下一条。

分布式锁机制

当存在多个消费者时,可以使用Redis或者ZooKeeper等工具提供的分布式锁机制,确保同一时刻只有一个消费者能够处理特定的消息。

消息重排序机制

  • 生产者:消息按任意顺序发送。
  • 消费者:
    • 读取一批消息后,根据消息的时间戳、业务标识等排序规则对消息排序。
    • 消费排序后的消息。

七、你会如何设计一个MQ?说说设计MQ思路?

首先这个 mq 得支持可伸缩性吧,就是需要的时候快速扩容,就可以增加吞吐量和容量,那怎么搞?

设计个分布式的系统呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了?

其次你得考虑一下这个 mq 的数据要不要落地磁盘吧?

那肯定要了,落磁盘才能保证别进程挂了数据就丢了。那落磁盘的时候怎么落啊?顺序写,这样就没有磁盘随机读写的寻址开销,磁盘顺序读写的性能是很高的,这就是 kafka 的思路。

其次你考虑一下你的 mq 的可用性啊?

这个事儿,具体参考之前可用性那个环节讲解的 kafka 的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务。能不能支持数据 0 丢失啊?可以的,参考我们之前说的那个 kafka 数据零丢失方案。

八、如何实现延时消息

延时消息就是一个消息需要延时多长时间才能够发送(也就是说,投递到MQ,延长指定时间才被消费),比如用户支付订单,如果多长时间未支付就会取消订单,这个就属于延时消息

实现延时消息的方法如下

数据库轮询

通过一个线程定时的去扫描数据库,通过订单时间来判断是否有超时的订单,然后进行update或delete等操作

JDK的延迟队列

利用JDK自带的DelayQueue来实现,这是一个无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入DelayQueue中的对象,是必须实现Delayed接口的。

时间轮算法

RabbitMQ

可以采用RabbitMQ的死信队列来实现延时队列,RabbitMQ可以针对Queue和Message设置 xmessage-tt,来控制消息的生存时间,如果超时,则消息变为dead letter,dead letter会被投递到死信交换器,然后通过死信队列将消息发送出去

RocketMQ

RocketMQ可以实现18个等级的消息延时,但是不可以实现任意时间的消息延时,使用RocketMQ的延时消息只需要按照正常消息发送,并指定延时等级即可,简单高效,并且这个延时时间可以在

RocketMQ的配置参数中进行配置

九、谈谈RocketMQ与Kafka的区别

业务为什么使用rocketmq 不用kafka

因为kafka的诞生是作为大数据的一个中间件来使用的,MQ只是kafka的一个功能,相对于RocketMQ,Kafka的功能相对于简单,RocketMQ设计的时候借鉴了很多kafka的设计,有着后发优势,支持分布式、集群、副本等机制,消息延时也比较少,但是RocketMQ也有很多kafka不具备的功能,比如:严格顺序消息,延时消息,服务端tag过滤,能够至少保证消费一个的可靠性策略,消息失败后重试时间随着次数递增等都是很多业务所需要的,并且RocketMQ是经过了双十一的验证,所以很多人说RocketMQ是专门为业务而生的。

为什么kafka不能支持大量的topic

这句话如果严格意义上说的话应该是kafka在topic-partition过多而不是单纯的topic过多

这个要从kafka的存储结构来说起,kafka的最小存储单元是一个partition,一个partition由一个数据文件以及一个索引文件组成,partition的存储文件是通过顺序写的方式来保证写入磁盘的效率的,但是如果非常多的partition需要磁盘写入,那么就可能造成顺序写变成随机写,因为磁盘的IO流量就那麽大,同时由很多个partition需要写入,就会变成随机写,性能反而会急剧下降,并且partition过多还是导致元数据管理,副本同步的困难,这些都是导致kafka不能支持大量topic的原因。

为什么RcoketMQ可以支持大量的Topic

这个需要从RocketMQ的存储结构来说,RocketMQ的所有的数据存储在一个commitlog,然后则会通过异步线程将commitlog的数据转移到其他对应的消费者的队列中,因为不管多少个队列也只有一个commitlog文件,所有写入以及读取性能不会随着队列的增加而有显著的变化

相关推荐
许苑向上3 分钟前
HttpServletRequest、ServerHttpRequest 和 ServerWebRequest作用详解
java·tomcat·mvc
千航@abc3 分钟前
中间件tomcat的结构与组件解释
java·中间件·tomcat
小沈熬夜秃头中୧⍤⃝19 分钟前
fnOS生态下的WordPress个人网站从本地到公网访问的搭建与配置
java·开发语言
鸿即为江边鸟36 分钟前
Java UDP 通信:实现简单的 Echo 服务器与客户端
java
八股文领域大手子40 分钟前
Synchronized解析
java·数据库·sql·mysql
码熔burning43 分钟前
(二 十 一)趣学设计模式 之 访问者模式!
java·设计模式·访问者模式
浮生若梦l1 小时前
原生android 打包.aar到uniapp使用
android·java·uni-app
孑么1 小时前
力扣 最长回文子串
java·数据结构·算法·leetcode·职场和发展·动态规划
开开心心就好1 小时前
高效玩转 PDF:实用的分割、合并操作详解
android·java·网络·windows·智能手机·pdf·软件工程
流光听风语1 小时前
【基础1】冒泡排序
java·数据结构·算法