在 GitHub / Gitee 编辑 消息队列面试场景 面试官:你好。 候选人:你好。 (面试官在你的简历上面看到了,呦,有个亮点,你在项目里用过 MQ ,比如说你用过 ActiveMQ ) 面试官:你在系统里用过消息队列吗?(面试官在随和的语气中展开了面试) 候选人:用过的(此时感觉没啥) 面试官:那你说一下你们在项目里是怎么用消息队列的? 候选人:巴拉巴拉,“我们啥啥系统发送个啥啥消息到队列,别的系统来消费啥啥的。比如我 们有个订单系统,订单系统每次下一个新的订单的时候,就会发送一条消息到 ActiveMQ 里 面去,后台有个库存系统负责获取消息然后更新库存。” (部分同学在这里会进入一个误区,就是你仅仅就是知道以及回答你们是怎么用这个消息队列 的,用这个消息队列来干了个什么事情?) 面试官:那你们为什么使用消息队列啊?你的订单系统不发送消息到 MQ ,直接订单系统调 用库存系统一个接口,咔嚓一下,直接就调用成功,库存不也就更新了。 候选人:额。。。(楞了一下,为什么?我没怎么仔细想过啊,老大让用就用了),硬着头皮 胡言乱语了几句。 (面试官此时听你楞了一下,然后听你胡言乱语了几句,开始心里觉得有点儿那什么了,怀疑 你之前就压根儿没思考过这问题) 面试官:那你说说用消息队列都有什么优点和缺点? (面试官此时心里想的是,你的 MQ 在项目里为啥要用,你没怎么考虑过,那我稍微简单点 儿,我问问你消息队列你之前有没有考虑过如果用的话,优点和缺点分别是啥?) 候选人:这个。。。(确实平时没怎么考虑过这个问题啊。。。胡言乱语了) (面试官此时心里已经更觉得你这哥儿们不行,平时都没什么思考) 面试官: Kafka 、 ActiveMQ 、 RabbitMQ 、 RocketMQ 都有什么区别?(面试官问你这个问题,就是说,绕过比较虚的话题,直接看看你对各种 MQ 中间件是否了 解,是否做过功课,是否做过调研) 候选人:我们就用过 ActiveMQ ,所以别的没用过。。。区别,也不太清楚。。。 (面试官此时更是觉得你这哥儿们平时就是瞎用,根本就没什么思考,觉得不行) 面试官:那你们是如何保证消息队列的高可用啊? 候选人:这个。。。我平时就是简单走 API 调用一下,不太清楚消息队列怎么部署的。。。 面试官:如何保证消息不被重复消费啊?如何保证消费的时候是幂等的啊? 候选人:啥?( MQ 不就是写入&消费就可以了,哪来这么多问题) 面试官:如何保证消息的可靠性传输啊?要是消息丢失了怎么办啊? 候选人:我们没怎么丢过消息啊。。。 面试官:那如何保证消息的顺序性? 候选人:顺序性?什么意思?我为什么要保证消息的顺序性?它不是本来就有顺序吗? 面试官:如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百 万消息持续积压几小时,说说怎么解决? 候选人:不是,我这平时没遇到过这些问题啊,就是简单用用,知道 MQ 的一些功能。 面试官:如果让你写一个消息队列,该如何进行架构设计啊?说一下你的思路。 候选人:。。。。。我还是走吧。。。。 这其实是面试官的一种面试风格,就是说面试官的问题不是发散的,而是从一个小点慢慢铺 开。比如说面试官可能会跟你聊聊高并发话题,就这个话题里面跟你聊聊缓存、 MQ 等等东 西,由浅入深,一步步深挖。 其实上面是一个非常典型的关于消息队列的技术考察过程,好的面试官一定是从你做过的某一 个点切入,然后层层展开深入考察,一个接一个问,直到把这个技术点刨根问底,问到最底 层。 面试题 为什么使用消息队列?消息队列有什么优点和缺点? Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景? 面试官心理分析 其实面试官主要是想看看: 第一,你知不知道你们系统里为什么要用消息队列这个东西? 不少候选人,说自己项目里用了 Redis、MQ,但是其实他并不知道自己为什么要用这个东西。 其实说白了,就是为了用而用,或者是别人设计的架构,他从头到尾都没思考过。 没有对自己的架构问过为什么的人,一定是平时没有思考的人,面试官对这类候选人印象通常 很不好。因为面试官担心你进了团队之后只会木头木脑的干呆活儿,不会自己思考。 第二,你既然用了消息队列这个东西,你知不知道用了有什么好处&坏处? 你要是没考虑过这个,那你盲目弄个 MQ 进系统里,后面出了问题你是不是就自己溜了给公司 留坑?你要是没考虑过引入一个技术可能存在的弊端和风险,面试官把这类候选人招进来了, 基本可能就是挖坑型选手。就怕你干 1 年挖一堆坑,自己跳槽了,给公司留下无穷后患。 第三,既然你用了 MQ,可能是某一种 MQ,那么你当时做没做过调研? 你别傻乎乎的自己拍脑袋看个人喜好就瞎用了一个 MQ,比如 Kafka,甚至都从没调研过业界流 行的 MQ 到底有哪几种。每一个 MQ 的优点和缺点是什么。每一个 MQ 没有绝对的好坏,但是 就是看用在哪个场景可以扬长避短,利用其优势,规避其劣势。 如果是一个不考虑技术选型的候选人招进了团队,leader 交给他一个任务,去设计个什么系 统,他在里面用一些技术,可能都没考虑过选型,最后选的技术可能并不一定合适,一样是留 坑。 面试题剖析 为什么使用消息队列 其实就是问问你消息队列都有哪些使用场景,然后你项目里具体是什么场景,说说你在这个场 景里用消息队列是什么? 面试官问你这个问题,期望的一个回答是说,你们公司有个什么业务场景,这个业务场景有 个什么技术挑战,如果不用 MQ 可能会很麻烦,但是你现在用了 MQ 之后带给了你很多的好 处。先说一下消息队列常见的使用场景吧,其实场景有很多,但是比较核心的有 3 个:解耦、异 步、削峰。 解耦 看这么个场景。A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数 据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃...... 在这个场景中,A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数 据,很多系统都需要 A 系统将这个数据发送过来。A 系统要时时刻刻考虑 BCDE 四个系统如果 挂了该咋办?要不要重发,要不要把消息存起来?头发都白了啊! 如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消 费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消 对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护 这个代码,也不需要考虑人家是否调用成功、失败超时等情况。总结:通过一个 MQ,Pub/Sub 发布订阅消息这么一个模型,A 系统就跟其它系统彻底解耦了。 面试技巧:你需要去考虑一下你负责的系统中是否有类似的场景,就是一个系统或者一个模 块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用 是不需要直接同步调用接口的,如果用 MQ 给它异步化解耦,也是可以的,你就需要去考虑在 你的项目里,是不是可以运用这个 MQ 去进行系统的解耦。在简历中体现出来这块东西,用 MQ 作解耦。 异步 再来看一个场景,A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库, 自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器 发起请求,等待个 1s,这几乎是不可接受的。一般互联网类的企业,对于用户直接的操作,一般要求是每个请求都必须在 200 ms 以内完成, 对用户几乎是无感知的。 如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一 个请求到返回响应给用户,总时长是 3 + 5 = 8ms,对于用户而言,其实感觉上就是点个按钮, 8ms 以后就直接返回了,爽!网站做得真好,真快!削峰 每天 0:00 到 12:00,A 系统风平浪静,每秒并发请求数量就 50 个。结果每次一到 12:00 ~ 13:00 ,每秒并发请求数量突然会暴增到 5k+ 条。但是系统是直接基于 MySQL 的,大量的请求涌入 MySQL,每秒钟对 MySQL 执行约 5k 条 SQL。 一般的 MySQL,扛到每秒 2k 个请求就差不多了,如果每秒请求到 5k 的话,可能就直接把 MySQL 给打死了,导致系统崩溃,用户也就没法再使用系统了。 但是高峰期一过,到了下午的时候,就成了低峰期,可能也就 1w 的用户同时在网站上操作, 每秒中的请求数量可能也就 50 个请求,对整个系统几乎没有任何的压力。 如果使用 MQ,每秒 5k 个请求写入 MQ,A 系统每秒钟最多处理 2k 个请求,因为 MySQL 每秒钟 最多处理 2k 个。A 系统从 MQ 中慢慢拉取请求,每秒钟就拉取 2k 个请求,不要超过自己每秒 能处理的最大请求数量就 ok,这样下来,哪怕是高峰期的时候,A 系统也绝对不会挂掉。而 MQ 每秒钟 5k 个请求进来,就 2k 个请求出去,结果就导致在中午高峰期( 1 个小时),可能有 几十万甚至几百万的请求积压在 MQ 中。这个短暂的高峰期积压是 ok 的,因为高峰期过了之后,每秒钟就 50 个请求进 MQ,但是 A 系 统依然会按照每秒 2k 个请求的速度在处理。所以说,只要高峰期一过,A 系统就会快速将积压 的消息给解决掉。 消息队列有什么优缺点 优点上面已经说了,就是在特殊场景下有其对应的好处,解耦、异步、削峰。 缺点有以下几个: 系统可用性降低 系统引入的外部依赖越多,越容易挂掉。本来你就是 A 系统调用 BCD 三个系统的接口就好了, ABCD 四个系统还好好的,没啥问题,你偏加个 MQ 进来,万一 MQ 挂了咋整?MQ 一挂,整套 系统崩溃,你不就完了?如何保证消息队列的高可用,可以点击这里查看。 系统复杂度提高 硬生生加个 MQ 进来,你怎么保证消息没有重复消费?怎么处理消息丢失的情况?怎么保证 消息传递的顺序性?头大头大,问题一大堆,痛苦不已。 一致性问题 A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个 系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处 做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个 数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。 Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点? 特性 ActiveMQ RabbitMQ RocketMQ Kafka 单机 吞吐 量 万级,比 RocketMQ、 Kafka 低一 个数量级 同 ActiveMQ 10 万级,支撑高吞 吐 10 万级,高吞吐,一般配 合大数据类的系统来进行 实时数据计算、日志采集 等场景 topic 数量 对吞 吐量 的影 响 topic 可以达到几百/ 几千的级别,吞吐量 会有较小幅度的下 降,这是 RocketMQ 的一大优势,在同等 机器下,可以支撑大 量的 topic topic 从几十到几百个时 候,吞吐量会大幅度下 降,在同等机器下,Kafka 尽量保证 topic 数量不要过 多,如果要支撑大规模的 topic,需要增加更多的机 器资源 时效 性 ms 级 微秒级, 这是 RabbitMQ 的一大特 点,延迟 最低 ms 级 延迟在 ms 级以内 可用 性 高,基于主 从架构实现 高可用 同 ActiveMQ 非常高,分布式架构 非常高,分布式,一个数 据多个副本,少数机器宕 机,不会丢失数据,不会 导致不可用 消息 可靠 性 有较低的概 率丢失数据 基本不丢 经过参数优化配置, 可以做到 0 丢失 同 RocketMQ 功能 支持 MQ 领域的 功能极其完 备 基于 erlang 开 发,并发 能力很 强,性能 极好,延 时很低 MQ 功能较为完善, 还是分布式的,扩展 性好 功能较为简单,主要支持 简单的 MQ 功能,在大数 据领域的实时计算以及日 志采集被大规模使用 综上,各种对比之后,有如下建议: 一般的业务系统要引入 MQ,最早大家都用 ActiveMQ,但是现在确实大家用的不多了,没经过 大规模吞吐量场景的验证,社区也不是很活跃,所以大家还是算了吧,我个人不推荐用这个 了;后来大家开始用 RabbitMQ,但是确实 erlang 语言阻止了大量的 Java 工程师去深入研究和掌控 它,对公司而言,几乎处于不可控的状态,但是确实人家是开源的,比较稳定的支持,活跃度 也高; 不过现在确实越来越多的公司会去用 RocketMQ,确实很不错,毕竟是阿里出品,但社区可能有 突然黄掉的风险(目前 RocketMQ 已捐给 Apache,但 GitHub 上的活跃度其实不算高)对自己 公司技术实力有绝对自信的,推荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有活 跃的开源社区,绝对不会黄。 所以中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;大 型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。 如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区 活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。 面试题 如何保证消息队列的高可用? 面试官心理分析 如果有人问到你 MQ 的知识,高可用是必问的。上一讲提到,MQ 会导致系统可用性降低。 所以只要你用了 MQ,接下来问的一些要点肯定就是围绕着 MQ 的那些缺点怎么来解决了。 要是你傻乎乎的就干用了一个 MQ,各种问题从来没考虑过,那你就杯具了,面试官对你的感 觉就是,只会简单使用一些技术,没任何思考,马上对你的印象就不太好了。这样的同学招进 来要是做个 20k 薪资以内的普通小弟还凑合,要是做薪资 20k+ 的高工,那就惨了,让你设计个 系统,里面肯定一堆坑,出了事故公司受损失,团队一起背锅。 面试题剖析 这个问题这么问是很好的,因为不能问你 Kafka 的高可用性怎么保证?ActiveMQ 的高可用性怎 么保证?一个面试官要是这么问就显得很没水平,人家可能用的就是 RabbitMQ,没用过 Kafka,你上来问人家 Kafka 干什么?这不是摆明了***难人么。 所以有水平的面试官,问的是 MQ 的高可用性怎么保证?这样就是你用过哪个 MQ,你就说说 你对那个 MQ 的高可用性的理解。 RabbitMQ 的高可用性RabbitMQ 是比较有代表性的,因为是基于主从(非分布式)做高可用性的,我们就以 RabbitMQ 为例子讲解第一种 MQ 的高可用性怎么实现。 RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式。 单机模式 单机模式,就是 Demo 级别的,一般就是你本地启动了玩玩儿的
标签:面试题,缓存,服务,进阶,一个,Redis,调用,Java,数据 From: https://www.cnblogs.com/shan13936/p/17469517.html