jjzjj

大数据面试杀招——Spark高频考点,必知必会!

大数据梦想 2023-03-28 原文
        前面两篇文章分别为大家介绍了大数据面试杀招 关于Hive 与 Hadoop 的内容,收到读者朋友们一致的好评和赞赏。嘿嘿,本篇文章我们就继续来研究,关于Spark的面试热点,又有哪些~


一、你是怎么理解Spark,它的特点是什么?

        Spark是一个基于内存的,用于大规模数据处理(离线计算、实时计算、快速查询(交互式查询))统一分析引擎

        它内部的组成模块,包含SparkCore,SparkSQL,SparkStreaming,SparkMLlib,SparkGraghx等…


        它的特点:

        Spark计算速度是MapReduce计算速度的10-100倍

  • 易用
        MR支持1种计算模型,Spsark支持更多的计算模型(算法多)

  • 通用
        Spark 能够进行离线计算、交互式查询(快速查询)、实时计算、机器学习、图计算

  • 兼容性
        Spark支持大数据中的Yarn调度,支持mesos。可以处理hadoop计算的数据。

        

二、Spark有几种部署方式,请分别简要论述

        1) Local:运行在一台机器上,通常是练手或者测试环境。

        2)Standalone:构建一个基于Mster+Slaves的资源调度集群,Spark任务提交给Master运行。是Spark自身的一个调度系统。

        3)Yarn: Spark客户端直接连接Yarn,不需要额外构建Spark集群。有yarn-client和yarn-cluster两种模式,主要区别在于:Driver程序的运行节点。

        4)Mesos:国内大环境比较少用。

        

三、Spark提交作业的参数

        因为我们Spark任务是采用的Shell脚本进行提交,所以一定会涉及到几个重要的参数,而这个也是在面试的时候容易被考察到的“细节”。

executor-cores —— 每个executor使用的内核数,默认为1,官方建议2-5个,我们企业是4个 num-executors —— 启动executors的数量,默认为2 executor-memory —— executor内存大小,默认1G driver-cores —— driver使用内核数,默认为1 driver-memory —— driver内存大小,默认512M        

四、简述Spark的作业提交流程

        Spark的任务提交方式实际上有两种,分别是YarnClient模式和YarnCluster模式。大家在回答这个问题的时候,也需要分类去介绍。千万不要被冗长的步骤吓到,一定要学会总结差异,发现规律,通过图形去增强记忆。

  • YarnClient 运行模式介绍

        在YARN Client模式下,Driver在任务提交的本地机器上运行,Driver启动后会和ResourceManager通讯申请启动ApplicationMaster,随后ResourceManager分配container,在合适的NodeManager上启动ApplicationMaster,此时的ApplicationMaster的功能相当于一个ExecutorLaucher,只负责向ResourceManager申请Executor内存。

        ResourceManager接到ApplicationMaster的资源申请后会分配container,然后ApplicationMaster在资源分配指定的NodeManager上启动Executor进程,Executor进程启动后会向Driver反向注册,Executor全部注册完成后Driver开始执行main函数,之后执行到Action算子时,触发一个job,并根据宽依赖开始划分stage,每个stage生成对应的taskSet,之后将task分发到各个Executor上执行。
        

  • YarnCluster 模式介绍

         在YARN Cluster模式下,任务提交后会和ResourceManager通讯申请启动ApplicationMaster,随后ResourceManager分配container,在合适的NodeManager上启动ApplicationMaster,此时的ApplicationMaster就是Driver

        Driver启动后向ResourceManager申请Executor内存,ResourceManager接到ApplicationMaster的资源申请后会分配container,然后在合适的NodeManager上启动Executor进程,Executor进程启动后会向Driver反向注册,Executor全部注册完成后Driver开始执行main函数,之后执行到Action算子时,触发一个job,并根据宽依赖开始划分stage,每个stage生成对应的taskSet,之后将task分发到各个Executor上执行。

        

五、你是如何理解Spark中血统(RDD)的概念?它的作用是什么?

        RDD 可是Spark中最基本的数据抽象,我想就算面试不被问到,那自己是不是也应该非常清楚呢!

        下面提供菌哥的回答,供大家参考:

  • 概念
        RDD是弹性分布式数据集,是Spark中最基本的数据抽象,代表一个不可变、可分区、里面的元素可并行计算 的集合。

  • 作用
        提供了一个抽象的数据模型,将具体的应用逻辑表达为一系列转换操作(函数)。另外不同RDD之间的转换操作之间还可以形成依赖关系,进而实现管道化,从而避免了中间结果的存储,大大降低了数据复制、磁盘IO和序列化开销,并且还提供了更多的API(map/reduec/filter/groupBy…)

        如果还想锦上添花,可以添上这一句:

RDD在Lineage依赖方面分为两种Narrow DependenciesWide Dependencies,用来解决数据容错时的高效性以及划分任务时候起到重要作用

六、简述Spark的宽窄依赖,以及Spark如何划分stage,每个stage又根据什么决定task个数?

        Spark的宽窄依赖问题是SparkCore部分的重点考察内容,多数出现在笔试中,大家需要注意。

        窄依赖:父RDD的一个分区只会被子RDD的一个分区依赖

        宽依赖:父RDD的一个分区会被子RDD的多个分区依赖(涉及到shuffle)

        那Stage是如何划分的呢?

        根据RDD之间的依赖关系的不同将Job划分成不同的Stage,遇到一个宽依赖则划分一个Stage。

        每个stage又根据什么决定task个数?

        Stage是一个TaskSet,将Stage根据分区数划分成一个个的Task。

        这里为了方便大家理解,贴上一张过程图

七、列举Spark常用的transformation和action算子,有哪些算子会导致Shuffle?

        我们在Spark开发过程中,避不开与各种算子打交道,其中Spark 算子分为transformation 和 action 算子,下面列出一些常用的算子,具体的功能还需要小伙伴们自行去了解。

  • transformation

  • map

  • mapRartition

  • flatMap

  • filter

  • action

  • reduce

  • collect

  • first

  • take

        如果面试官问你,那小伙叽,有哪些会引起Shuffle过程的Spark算子呢?

        你只管自信的回答:

  • reduceByKey
  • groupByKey
  • …ByKey

八、reduceByKey与groupByKey的区别,哪一种更具优势?

        既然你上面都提到 reduceByKey 和groupByKey ,那哪一种更具优势,你能简单分析一下吗?

        能问这样的问题,已经暗示面试官的水平不低了,那么我们该如何回答呢:

        reduceByKey:按照key进行聚合,在shuffle之前有combine(预聚合)操作,返回结果是RDD[k,v]。

        groupByKey:按照key进行分组,直接进行shuffle

        所以,在实际开发过程中,reduceByKey比groupByKey,更建议使用。但是需要注意是否会影响业务逻辑

        

九、Repartition和Coalesce 的关系与区别,能简单说说吗?

        这道题就已经开始参和有“源码”的味道了,为什么呢?

        1)关系:

        两者都是用来改变RDD的partition数量的,repartition底层调用的就是coalesce方法:coalesce(numPartitions, shuffle = true)

        2)区别:

        repartition一定会发生shuffle,coalesce 根据传入的参数来判断是否发生shuffle。

        一般情况下增大rdd的partition数量使用repartition,减少partition数量时使用coalesce

        

十、简述下Spark中的缓存(cache和persist)与checkpoint机制,并指出两者的区别和联系

        关于Spark缓存和检查点的区别,大致可以从这3个角度去回答:

  • 位置
        Persist 和 Cache将数据保存在内存,Checkpoint将数据保存在HDFS

  • 生命周期
        Persist 和 Cache 程序结束后会被清除或手动调用unpersist方法,Checkpoint永久存储不会被删除。

  • RDD依赖关系
        Persist 和 Cache,不会丢掉RDD间的依赖链/依赖关系,CheckPoint会斩断依赖链。

        

十一、简述Spark中共享变量(广播变量和累加器)的基本原理与用途

        关于Spark中的广播变量和累加器的基本原理和用途,答案较为固定,大家无需刻意去记忆。

        累加器(accumulator)是Spark中提供的一种分布式的变量机制,其原理类似于mapreduce,即分布式的改变,然后聚合这些改变。累加器的一个常见用途是在调试时对作业执行过程中的事件进行计数

        广播变量是在每个机器上缓存一份,不可变,只读的,相同的变量,该节点每个任务都能访问,起到节省资源和优化的作用。它通常用来高效分发较大的对象。

        

十二、当Spark涉及到数据库的操作时,如何减少Spark运行中的数据库连接数?

        嗯,有点“调优”的味道,感觉真正的“风暴”即将到来,这道题还是很好回答的,我们只需要减少连接数据库的次数即可。

        使用foreachPartition代替foreach,在foreachPartition内获取数据库的连接。
        

十三、能介绍下你所知道和使用过的Spark调优吗?

        恐怖如斯,该来的还是会来的,庆幸自己看了菌哥的面试杀招,丝毫不慌:
        

资源参数调优

  • num-executors:设置Spark作业总共要用多少个Executor进程来执行
  • executor-memory:设置每个Executor进程的内存
  • executor-cores:设置每个Executor进程的CPU core数量
  • driver-memory:设置Driver进程的内存
  • spark.default.parallelism:设置每个stage的默认task数量

开发调优

  1. 避免创建重复的RDD
  2. 尽可能复用同一个RDD
  3. 对多次使用的RDD进行持久化
  4. 尽量避免使用shuffle类算子
  5. 使用map-side预聚合的shuffle操作
  6. 使用高性能的算子
①使用reduceByKey/aggregateByKey替代groupByKey
②使用mapPartitions替代普通map
③使用foreachPartitions替代foreach
④使用filter之后进行coalesce操作
⑤使用repartitionAndSortWithinPartitions替代repartition与sort类操作

  1. 广播大变量
在算子函数中使用到外部变量时,默认情况下,Spark会将该变量复制多个副本,通过网络传输到task中,此时每个task都有一个变量副本。如果变量本身比较大的话(比如100M,甚至1G),那么大量的变量副本在网络中传输的性能开销,以及在各个节点的Executor中占用过多内存导致的频繁GC(垃圾回收),都会极大地影响性能。

  1. 使用Kryo优化序列化性能
  2. 优化数据结构
在可能以及合适的情况下,使用占用内存较少的数据结构,但是前提是要保证代码的可维护性。

        如果能够尽可能的把这些要点说出来,我想面试官可能就一个想法:

十四、如何使用Spark实现TopN的获取(描述思路或使用伪代码)?

        能让你使用伪代码来描述这已经非常“苛刻”了,但是不慌,这里提供3种思路供大家参考:

        

  • 方法1:
        (1)按照key对数据进行聚合(groupByKey)

        (2)将value转换为数组,利用scala的sortBy或者sortWith进行排序(mapValues)

        注意:当数据量太大时,会导致OOM

  • 方法2:
        (1)取出所有的key

        (2)对key进行迭代,每次取出一个key利用spark的排序算子进行排序

  • 方法3:
        (1)自定义分区器,按照key进行分区,使不同的key进到不同的分区

        (2)对每个分区运用spark的排序算子进行排序


彩蛋

        为了能鼓励大家多学会总结,菌在这里贴上自己平时做的思维导图,需要的朋友,可以关注博主个人微信公众号【猿人菌】,后台回复“思维导图”即可获取。


        

结语

        很高兴能在文末看见你,朋友,有任何好的想法或者建议都可以在评论区留言,或者直接私信我也ok,后期会考虑出一些大数据面试的场景题,在最美的年华,做最好的自己,我是00后Alice,我们下一期见~~


有关大数据面试杀招——Spark高频考点,必知必会!的更多相关文章

  1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  2. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  3. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  4. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  5. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  6. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  7. 【Java 面试合集】HashMap中为什么引入红黑树,而不是AVL树呢 - 2

    HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候

  8. ruby-on-rails - 创建 ruby​​ 数据库时惰性符号绑定(bind)失败 - 2

    我正在尝试在Rails上安装ruby​​,到目前为止一切都已安装,但是当我尝试使用rakedb:create创建数据库时,我收到一个奇怪的错误:dyld:lazysymbolbindingfailed:Symbolnotfound:_mysql_get_client_infoReferencedfrom:/Library/Ruby/Gems/1.8/gems/mysql2-0.3.11/lib/mysql2/mysql2.bundleExpectedin:flatnamespacedyld:Symbolnotfound:_mysql_get_client_infoReferencedf

  9. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  10. SPI接收数据异常问题总结 - 2

    SPI接收数据左移一位问题目录SPI接收数据左移一位问题一、问题描述二、问题分析三、探究原理四、经验总结最近在工作在学习调试SPI的过程中遇到一个问题——接收数据整体向左移了一位(1bit)。SPI数据收发是数据交换,因此接收数据时从第二个字节开始才是有效数据,也就是数据整体向右移一个字节(1byte)。请教前辈之后也没有得到解决,通过在网上查阅前人经验终于解决问题,所以写一个避坑经验总结。实际背景:MCU与一款芯片使用spi通信,MCU作为主机,芯片作为从机。这款芯片采用的是它规定的六线SPI,多了两根线:RDY和INT,这样从机就可以主动请求主机给主机发送数据了。一、问题描述根据从机芯片手

随机推荐