热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java面试题冲刺第十四天消息队列

这篇文章主要为大家分享了最有价值的三道关于消息队列的面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,感兴趣的

面试题1:说说你对消息队列的理解,消息队列为了解决什么问题?

我们公司业务系统一开始体量较小,很多组件都是单机版就足够,后来随着用户量逐渐扩大,我们程序也采用了微服务的设计思想,把很多服务进行了拆分,但后来在一些秒杀抢票活动或高频业务中,服务依旧扛不住大量QPS,因此我们引入了消息队列来优化该类问题。

消息队列应用的场景大致分为三类:解耦异步削峰

解耦

消息队列类似设计模式中的观察者模式(Observer)发布-订阅模式(Pub-Sub)。生产者生成和发送消息到消息队列,消费者从消息队列中取走消息进行处理,称为消费,使用消息队列将“生产者”和“消费者”之间的操作关联解耦,易于扩展。

在这里插入图片描述

比如系统A为支付系统,一开始用户支付完调用日志记录系统B记录就完了,后来内容越来越多,支付完成要调用加积分系统C、短信通知系统D、优惠券系统E等等…

在这里插入图片描述

这个场景中,A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条支付成功的数据,很多系统接口都需要 A 系统调用把支付成功的数据发送过去。A 系统程序员要时刻考虑这些问题:

  • 其他系统如果挂了该咋办?是不是直接程序抛异常了?
  • 一天到晚加业务,每次都重新部署?领导是不是狗?

那如果引入 MQ,A 系统产生一条数据,发送到 MQ 里面去,每个子系统加上对消息队列中支付成功消息的订阅,持续监听就可以了,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。

在这里插入图片描述

这样下来,A系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况,我只负责把支付成功的信息放到MQ里就行了,至于能否正常加积分、能否正常短信通知,管我鸟事!~~可见,通过一个 MQ,Pub/Sub 发布订阅消息这么一个模型,A 系统就跟其它系统彻底解耦了。

面试官:哦,那我听出来了,你这是喜欢甩锅啊!来,简历还你。

在这里插入图片描述

我:额。。不,我开玩笑的,当然不能这样做,这里其实涉及到MQ在分布式事务中数据一致性的问题;听我跟您解释。

数据一致性

这个其实是分布式服务本身就存在的一个问题,不仅仅是消息队列的问题,但是放在这里说是因为用了消息队列这个问题会更明显。

就像咱们上面说的,你支付成功的服务自己保证自己的逻辑成功处理了,你成功发了消息,但是短信系统,积分系统等等这么多系统,他们成功还是失败你就不管了?当然不行,这样坑队友的行为,狄大人都帮不了你~

怎么办?那就把所有的服务都放到一个事务里,所有都成功成功才能算这一次下单是成功的,要成功一起成功,要失败一起失败。

异步

A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、400ms、200ms。最终请求总延时是 3 + 300 + 400 + 200 = 903ms,接近 1秒,用户感觉搞个毛线?慢的一批。

在这里插入图片描述

一般互联网类的企业,对于用户直接的操作,一般要求是每个请求都必须在 200 ms 以内完成,对用户几乎是无感知的,如果1秒足以说明该系统不可用,垃圾系统。

如果这里使用了消息队列,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms,对于用户而言,其实感觉上就是点个按钮,8ms 以后就直接返回了,体验感很好

削峰

比如我们系统有代售抢票业务,平时每天QPS也就50左右,A 系统风平浪静。结果每次一到春运抢票,每秒并发请求数量突然会暴增到10000以上。但是系统是直接基于 MySQL 的,大量的请求直接打到 MySQL,比如一般MySQL能抗2000条请求,现在每秒10000 条 SQL,可能就直接把 MySQL 给打死了,导致系统崩溃。但是高峰期一过就又没人了,QPS回到50,对整个系统几乎没有任何的压力。

在这里插入图片描述

如果这里使用 MQ,每秒 1w 个请求写入 MQ,A 系统每秒钟最多处理 2000 个请求,因为 MySQL 每秒钟最多处理 2k 个。A 系统从 MQ 中慢慢拉取请求,每秒钟就拉取 2k 个请求,不要超过自己每秒能处理的最大请求数量就 ok了,这样下来,哪怕是高峰期的时候,A 系统也不会挂掉。当然了,用户的响应时间肯定会受影响,毕竟秒杀嘛,只要把前多少条请求处理好,其余的抢票失败就行了。

另外,MQ 每秒钟 1w 个请求进来,只处理 2k 个请求出去,结果会导致在中午高峰期,可能有几十万甚至几百万的请求积压在 MQ 中。

这个短暂的高峰期积压是 ok 的,因为高峰期过了之后,每秒钟就 50 个请求进 MQ,但是A 系统依然会按照每秒 2k 个请求的速度在处理。所以说,只要高峰期一过,A 系统就会快速将积压的消息给消费掉。

追问1:消息队列有什么优缺点

  • 系统可用性降低

系统引入的外部依赖越多,越容易挂掉。本来你就是 A 系统调用 BCD 三个系统的接口就好了,人 ABCD 四个系统好好的,没啥问题,你偏加个 MQ 进来,万一 MQ 挂了咋整,MQ 一挂,整套系统崩溃的,你不就完了?如何保证消息队列的高可用?

  • 系统复杂度提高

硬生生加个 MQ 进来,你怎么保证消息一定被消费?如何避免消息重复投递或重复消费?数据丢失怎么办?怎么保证消息传递的顺序性?

  • 一致性问题

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

面试题2:对于消息中间机,你们是怎么做技术选型的?

目前市面上比较主流的消息队列中间件主要有,Kafka、ActiveMQ、RabbitMQ、RocketMQ 等。

ActiveMQ和RabbitMQ这两由于吞吐量的原因,只有业务体量一般的公司在用,RabbitMQ由于是erlang语言开发的,我们都不了解,因此扩展和维护成本都很高,查个问题都头疼。

Kafka和RocketMQ一直在各自擅长的领域发光发亮,两者的吞吐量、可靠性、时效性等都很可观。

我们通过图表看看这几个消息中间机的对比:

在这里插入图片描述

大家其实一下子就能看到差距了,就拿吞吐量来说,早期比较活跃的ActiveMQ 和RabbitMQ基本上不是后两者的对手了,在现在这样大数据的年代吞吐量是真的很重要。

面试题3:如何确保消息正确地发送至 RabbitMQ?如何确保消息接收方消费了消息?

发送方确认模式

将信道设置成confirm模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一的ID。

一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认给生产者(包含消息唯一ID)。

如果RabbitMQ发生内部错误从而导致消息丢失,会发送一条Nack(not acknowledged,未确认)消息。

发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。

接收方确认机制

消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确认了消息,RabbitMQ才能安全地把消息从队列中删除。

这里并没有用到超时机制,RabbitMQ仅通过Consumer的连接中断来确认是否需要重新发送消息。也就是说,只要连接不中断,RabbitMQ给了Consumer足够长的时间来处理消息。保证数据的最终一致性;

追问1:如何保证MQ消息的可靠传输?

以我们常用的RabbitMQ为例,消息不可靠的情况可能是消息丢失,劫持等原因;

丢失又分为:生产者丢失消息、消息队列丢失消息、消费者丢失消息;

生产者丢失消息:从生产者弄丢数据这个角度来看,RabbitMQ提供confirm模式来确保生产者不丢消息;

confirm模式用的居多:一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一的ID(从1开始),一旦消息被投递到所有匹配的队列之后;RabbitMQ就会发送一个ACK给生产者(包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了;

如果rabbitMQ没能处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。

消息队列丢数据:消息持久化。

处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。

持久化配置和confirm机制配合使用,在消息持久化磁盘后,再给生产者发送一个Ack信号。

这样,如果消息持久化磁盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您关注编程笔记的更多内容!


推荐阅读
  • 分布式消息_58分布式消息队列WMB设计与实践
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了58分布式消息队列WMB设计与实践相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 恶意软件分析的最佳编程语言及其应用
    本文介绍了学习恶意软件分析和逆向工程领域时最适合的编程语言,并重点讨论了Python的优点。Python是一种解释型、多用途的语言,具有可读性高、可快速开发、易于学习的特点。作者分享了在本地恶意软件分析中使用Python的经验,包括快速复制恶意软件组件以更好地理解其工作。此外,作者还提到了Python的跨平台优势,使得在不同操作系统上运行代码变得更加方便。 ... [详细]
  • rabbtimq相关下载与安装
    rabbitmq与elang版本关系查看https:www.rabbitmq.comwhich-erlang.html#eol-series  rpm下载地址https:githu ... [详细]
  • 源码包安装RabbitMQ3.6
    先安装erlang依赖,也是门编程语言,下载源码包地址:https:www.erlang.orgdownloads20.1首先先安装个依赖 ... [详细]
  • 目录摘要SQL的现在NoSQL,NotOnlySQL要分布式,也要SQL总结引用摘要毫不夸张的说,关系数据库是企业软件系统的核心,企业形形色色信息行为的背后,都有关系数据库的支撑。 ... [详细]
  • 近期看见一篇来自Intel的很有意思的分析文章,作者提到在他向45名与会的各公司程序员开发经理战略师提问“什么是实施并行编程的最大障碍”时,下面五个因素 ... [详细]
  • Linux(阿里云服务器)安装RabbitMQ
    目录安装前的说明安装Socat安装Erlang安装RabbitMQ配置阿里云开放端口启动访问添加用户安装前的说明安装RabbitMQ前需要先安装Socat、Er ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了看大数据时代下的IT架构业界消息队列对比相关的知识,希望对你有一定的参考价值。一、MQ(MessageQue ... [详细]
  • 本文详细介绍了云服务器API接口的概念和作用,以及如何使用API接口管理云上资源和开发应用程序。通过创建实例API、调整实例配置API、关闭实例API和退还实例API等功能,可以实现云服务器的创建、配置修改和销毁等操作。对于想要学习云服务器API接口的人来说,本文提供了详细的入门指南和使用方法。如果想进一步了解相关知识或阅读更多相关文章,请关注编程笔记行业资讯频道。 ... [详细]
  • 什么是大数据lambda架构
    一、什么是Lambda架构Lambda架构由Storm的作者[NathanMarz]提出,根据维基百科的定义,Lambda架构的设计是为了在处理大规模数 ... [详细]
  • elixirerlang通过AyandaDubeFIPS(联邦信息处理标准)[1]是由NIST(美国国家标准技术研究院)定义 ... [详细]
  • Druid读取Kafka数据的简单配置过程
    Druid的单机版安装参考:https:blog.51cto.com101202752429912Druid实时接入Kafka的过程下载、安装、启动kafka过程:wgethttp ... [详细]
  • 分布式系统:并发系统概述
    分布式系统:并发系统概述分布式系统由多个独立的代码片段组成,它们在多个位置的许多处理节点 ... [详细]
author-avatar
多米音乐_34396075
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有