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

面试精讲之面试考点及大厂真题分布式专栏13项目中为什么要使用消息队列

13项目中为什么要使用消息队列学习从来无捷径,循序渐进登高峰。——高永祚引言上个章节把Redis夺命连环问掰扯完,面试还没有结束,消息

13项目中为什么要使用消息队列

 

 

学习从来无捷径,循序渐进登高峰。

—— 高永祚

 


引言

上个章节把Redis夺命连环问掰扯完,面试还没有结束,消息队列同样是面试中必问的,分布式构建三把斧:缓存+异步+数据分组,从这节开始进入异步解决方案-消息队列

生活中的队列:超市买菜排队付款,出去玩排队上飞机。
图片描述

(图片来源:https://medium.com/)

 

计算机系统中的队列:

凡是可以“排队”去做的事情,都可以使用消息队列。网上买东西同样也需要“排队付款”,但是有人说,我点确认付款后马上就显示成功了,没感觉到排队呀?其实在后台系统中是排了,只不过排队的时间对于人来说有点短,可能1-2秒就结束了,但是对于计算机来说,这1-2秒的时间很长了。大型分布式系统建设中,消息队列主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。消息发布者只管把消息发布到 MQ 中而不用管谁来取,消息使用者只管从 MQ 中取消息而不管是谁发布的。这样发布者和使用者都不用知道对方的存在。

Web应用程序毫无疑问有大量的代码执行HTTP请求/响应周期的一部分。这适用于更快的任务耗费数百毫秒内或更少。然而,有些处理,还需要耗时更多甚至最终会是一两秒钟缓慢的同步执行,在如此长时间的调用流转中,肯定有一些调用是可以不同步的,如下单送积分,用户下单是最主要的,送积分的操作可以异步去做,订单支付成功给用户的短信通知,返回支付订单进入下一环节更重好,短信通知可以异步去发送,为了应对诸如此类的异步操作,消息队列这门技术应运而生。
图片描述


 


1.面试官:你在项目中使用过消息队列吗?公司使用什么消息框架。

我:


我了解的常用消息队列中间件框架


  1. ActiveMQ:由 Apache 出品的一款开源消息中间件。
  2. RabbitMQ:Rabbit科技有限公司开发,使用Erlang语言开发的开源消息队列系统,基于AMQP协议来实现。
  3. RocketMQ:阿里巴巴自主开发,是淘宝内部的交易系统使用了淘宝自主研发的Notify消息中间件,使用MySQL作为消息存储媒介,可完全水平扩容。
  4. Kafka:最初是由领英开发,并随后于2011年初开源,并于2012年10月23日由Apache Incubator孵化出站。

这其中Kafka天生就是分布式设计队列的消息理论上可以分摊到无数服务节点上。同等硬件环境下 Kafka 的性能大大超过传统的 ActiveMQ、RabbitMQ等MQ实现,这是 Kafka 炙手可热的重要原因,我们使用的就是Kafka搭建的集群。

Tip:这只是一个开始,面试官可能顺着你的话题开始聊Kafka了,Kafka的特性我在后面单独讲一节,继续展开讲消息队列基础知识。


 


2.面试官:哪些业务场景使用了消息队列?

问题分析:
在我刚刚工作接触编程的时候,做的项目都是单机部署,一套框架走天下,根本没有机会使用到消息中间件,真正参与大型互联网公司的分布式系统后豁然开朗,原来系统之间通讯是这么轻松愉快。所以如果要拿到大厂offer,至少要了解一个消息框架。

我:

“一百字的定义,不如一句话的实例”

我在公司的核心部分负责的是订单核心系统(具体什么订单系统自行yy一个)。
图片描述

这是一个完整的外卖订单流程。

从普通用户的角度来看,一个外卖订单从下单后,会经历支付、商家接单、配送、用户收货、售后及订单完成多个阶段。

以技术的视角来分解的话,每个阶段依赖于多个子服务来共同完成,比如下单会依赖于购物车、订单预览、确认订单服务,这些子服务又会依赖于底层基础系统来完成其功能,总之就是一个订单从提单到完成,要经历一个非常庞杂的流程。

一个服务所需要处理的工作越少,其性能自然越高。可以通过将部分操作异步化来减少需要同步进行的操作,进而提升服务的性能。异步化有两种方案。


  1. 使用消息队列:异步操作通过接收消息完成。
  2. 使用多线程:将异步操作放在单独线程中处理,避免阻塞服务线程。

比如,日志收集,采集日志是系统中经常被需要的功能,业务系统(如订单系统)流量高,数量极大,响应时间要求高,如果想收集订单日志,收集日志的动作必然不可以影响订单主流程,采集日志过程就可以使用消息队列模型设计。
图片描述

再比如,收银系统,确认收款成功,通过MQ通知给物流系统发货,这些独立系统之间的通讯都需要使用MQ。

再比如,消费积分,用户每消费一笔给用户增加一定积分,京东豆,信用卡积分,在一个正规大厂的架构设计中,可以100%的确定订单系统和积分/奖励系统是耦合在一起的,那怎么通知积分系统给用户加积分?这个时候MQ就登场了。

面试官打断了我…


 


3.面试官:那为什么不能使用线程池开启多线程呢,可同样达到异步的效果?

问题分析: 千万不能被面试官所迷惑,他是想要你给出使用消息队列有什么好处。

我:

这个就要从使用消息队列有什么好处说起了,我总结了以下几点:


使用消息队列有什么好处:


  1. 异步处理模式

    比如上面说的日志收集功能,订单系统是消息发送者,一行代码发送一条日志消息而无须如何等待。消息发送者将消息发送到一条虚拟的通道(主题 或 队列)上,日志存储服务作为消息接收者监听该通道,这样做的好处就是收集日志不会阻碍主流程,日志积压在消息队列里,日志服务可以慢慢消化,也无需很高的性能。

    至于为什么不使用多线程来做,这就是我要说的第2点。

  2. 应用系统解耦

    订单服务和日志存储服务显然是两个服务,微服务时代,根据单一职责原则,订单系统只负责订单相关的工作,日志收集服务只负责收集日志,如果把这两件事通过线程池揉在一起,系统见界限就不明显了,做不到完全解耦。

  3. 流量削峰

    当在线api接口在应对高峰流量时,比如“秒杀”互动流量激增时,如果日志服务接口处理能力有限,可以先将日志消息积压在队列里,后台慢慢处理,防止日志服务被打挂。

  4. 发布/订阅(Producer–consumer)

    一条消息,可以广播给任意个收听方,Producer只负责发送消息 Message,Consumer可随意订阅 Message。就像广播一样,是系统之间跨机房跨机器通讯的主要手段。

    场景:电商系统中,订单服务和支付服务往往是分开部署在不同机房,订单系统确认订单,给用户跳转到支付页面,支付成功后,支付系统广播一条 Message,用户xxx已经确认付款,订单订阅了此消息,将要订单状态改成已支付,物流系统收到支付成功消息开始发货,整个流程,系统之间可以通过MQ通讯。
    图片描述


面试官欣慰地笑了,似乎对我对回答很满意,我似乎也猜到他接下来要问什么了,关于“使用消息队列有什么缺点”,不如我一次痛快讲完。


我:

凡事都有两面性,不能考虑到消息队列的优点,分布式环境下,消息中间件的介入后会为系统提高复杂度,对应就会需要解决方案,使用消息中间件会带来什么问题呢?


 


使用消息队列有什么缺点:


  1. 消息丢失问题: 任何系统不能保证万无一失,比如 Producer 发出了10000条消息,Consumer 只收到了 9999 个消息,万有1失,Consumer 能否接受丢一条?如果是订单成功短信可以接受丢一条,就是有一个顾客没有通知到已经发货,但货还是发出去了,如果是支付系统,用户已经付款却因为消息丢失没有通知到订单或物流系统,那恐怕顾客要找你麻烦了。
  2. 消息重复问题:如 Producer 发出了10000条消息,Consumer 只收到了 10001 条消息,有一条是重复的,业务能否接受一条重复的消息,这个是作为系统设计者要考虑的问题。
  3. 消息的顺序问题:如 Producer 发送顺序是123,Consumer 收到的消息是132,要考虑消费端是否对顺序敏感。
  4. 一致性问题: 如消息丢失问题真的发生且无法找回,会造成两个系统的数据最终不一致,如果消息延迟,会造成短暂不一致。

面试官:小伙子你考虑地非常全面,关于消息队列的基础就问到这。(面试官彻底被我折服)。

Tip:

针对上面的问题都是消息中间件系统带来的常见困扰,是否需要解决完全依赖业务场景,如果问题对系统产生影响低可以接受,可以忽略,如何解决,每种消息中间件系统设计方案也有所不同,还需要考虑从业务上解决,如消息重复问题,如果 Consumer 不能接受重复消息,那 Consumer 的接口可以设计成“幂等”,这样就不怕重复消息给系统造成影响。


 


总结

本文主要针对消息队列的概念和使用做了讲解,消息队列同缓存一样,几乎是互联网系统建设中不可缺少的,面试也会被考察,通常会从以下几个方面进行考察:


  1. 你熟悉哪些消息中间件,各自有什么优缺点。
  2. 为什么使用消息中间件?
  3. 消息队列使用场景。
  4. 使用消息中间件有什么缺点,如何解决。

推荐阅读
  • 本文探讨了Web开发与游戏开发之间的主要区别,旨在帮助开发者更好地理解两种开发领域的特性和需求。文章基于作者的实际经验和网络资料整理而成。 ... [详细]
  • 程序员如何优雅应对35岁职业转型?这里有深度解析
    本文探讨了程序员在职业生涯中如何通过不断学习和技能提升,优雅地应对35岁左右的职业转型挑战。我们将深入分析当前热门技术趋势,并提供实用的学习路径。 ... [详细]
  • 本文探讨了如何通过一系列技术手段提升Spring Boot项目的并发处理能力,解决生产环境中因慢请求导致的系统性能下降问题。 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
  • Spring Cloud Config 使用 Vault 作为配置存储
    本文探讨了如何在Spring Cloud Config中集成HashiCorp Vault作为配置存储解决方案,基于Spring Cloud Hoxton.RELEASE及Spring Boot 2.2.1.RELEASE版本。文章还提供了详细的配置示例和实践建议。 ... [详细]
  • 本文将详细介绍如何在ThinkPHP6框架中实现多数据库的部署,包括读写分离的策略,以及如何通过负载均衡和MySQL同步技术优化数据库性能。 ... [详细]
  • 本文探讨了浏览器的同源策略限制及其对 AJAX 请求的影响,并详细介绍了如何在 Spring Boot 应用中优雅地处理跨域请求,特别是当请求包含自定义 Headers 时的解决方案。 ... [详细]
  • 本文介绍了一个基于 Java SpringMVC 和 SSM 框架的综合系统,涵盖了操作日志记录、文件管理、头像编辑、权限控制、以及多种技术集成如 Shiro、Redis 等,旨在提供一个高效且功能丰富的开发平台。 ... [详细]
  • GoCV入门指南:配置与基础应用
    本文详细介绍了GoCV的安装配置及基本使用方法,包括如何打开摄像头、图片和视频文件。适合Golang开发者快速上手。 ... [详细]
  • 软件工程课堂测试2
    要做一个简单的保存网页界面,首先用jsp写出保存界面,本次界面比较简单,首先是三个提示语,后面是三个输入框,然 ... [详细]
  • 深入解析Hadoop的核心组件与工作原理
    本文详细介绍了Hadoop的三大核心组件:分布式文件系统HDFS、资源管理器YARN和分布式计算框架MapReduce。通过分析这些组件的工作机制,帮助读者更好地理解Hadoop的架构及其在大数据处理中的应用。 ... [详细]
  • JMeter接口关联与数据提取:正则表达式和JSON Extractor的使用
    在使用JMeter进行接口测试时,常常需要从前一个接口的响应中提取数据并应用于后续请求。本文将详细介绍如何利用正则表达式提取器(Regular Expression Extractor)和JSON Extractor来实现这一需求。 ... [详细]
  • Spring Cloud学习指南:深入理解微服务架构
    本文介绍了微服务架构的基本概念及其在Spring Cloud中的实现。讨论了微服务架构的主要优势,如简化开发和维护、快速启动、灵活的技术栈选择以及按需扩展的能力。同时,也探讨了微服务架构面临的挑战,包括较高的运维要求、分布式系统的复杂性、接口调整的成本等问题。最后,文章提出了实施微服务时应遵循的设计原则。 ... [详细]
  • 前言无论是对于刚入行工作还是已经工作几年的java开发者来说,面试求职始终是你需要直面的一件事情。首先梳理自己的知识体系,针对性准备,会有事半功倍的效果。我们往往会把重点放在技术上 ... [详细]
  • 本文深入探讨了JavaScript中实现继承的四种常见方法,包括原型链继承、构造函数继承、组合继承和寄生组合继承。对于正在学习或从事Web前端开发的技术人员来说,理解这些继承模式对于提高代码质量和维护性至关重要。 ... [详细]
author-avatar
minimiai_559
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有