spark2020面试题

文章目录

  • 一、RDD
  • 二、driver、Executor相关
  • 三、spark存储
  • 四、数据倾斜
  • 五、宽窄依赖、Stage、Job、task
  • 六、Spark性能优化
  • 七、并发
  • 八、pyspark内置函数、常用算子
  • 九、常见OOM类型报错,及解决办法
  • 十、集群资源
  • 十一、查看应用
  • 问题

一、RDD

1.spark中的RDD是什么,有哪些特性
答:RDD(Resilient Distributed Dataset)叫做分布式数据集,是spark中最基本的数据抽象,它代表一个不可变,可分区,里面的元素可以并行计算的集合。
Resilient:表示弹性的,弹性表示
Dataset:就是一个集合,用于存放数据的
Destributed:分布式,可以并行在集群计算
** 2. 抽象弹性分布式数据集对于Spark来说的弹性计算到底提现在什么地方?**
1)存和磁盘数据这两种存储方式的切换
Spark 可以使用 persist 和 cache 方法将任意 RDD 缓存到内存或者磁盘文件系统中。数据会优先存储到内存中,当内存不足以存放RDD中的数据的时候,就会持久化到磁盘上。这样,就可以最大化的利益内存以达到最高的计算效率;同时又有磁盘作为兜底存储方案以确保计算结果的正确性。
2)基于Linage的高效容错机制
Linage是用于记录RDD的父子依赖关系,子RDD会记录父RDD,且各个分片之间的数据互不影响。当出现错误的时候,只需要恢复单个Split的特定部分即可。
3)Task失败自动重试,Stage失败自动重试
TaskScheduler从每一个Stage的DAGScheduler中获取TaskSet,运行并校验是否存在故障。如果存在故障则会重试指定测试。
Stage对象可以记录并跟踪多个StageInfo,缺省的重试次数也是4次。且可以直接运行计算失败的阶段,值计算失败的数据分片。
4)数据调度弹性
3. RDD有哪些特性

  1. 分区
    每一个 RDD 包含的数据被存储在系统的不同节点上,是由很多分区组成的,操作RDD的时候,对RDD里面的每一个分区进行操作。而这些操作真正的会分发到每台机器上,并且拥有容错机制。
    在物理存储中,每个分区指向一个存储在内存或者硬盘中的数据块 (Block) ,其实这个数据块就是每个 task 计算出的数据块,它们可以分布在不同的节点上。
    所以,RDD 只是抽象意义的数据集合,分区内部并不会存储具体的数据,只会存储它在该 RDD 中的 index,通过该 RDD 的 ID 和分区的 index 可以唯一确定对应数据块的编号,然后通过底层存储层的接口提取到数据进行处理。
    在集群中,各个节点上的数据块会尽可能的存储在内存中,只有当内存没有空间时才会放入硬盘存储,这样可以最大化的减少硬盘 IO 的开销。
  2. 不可变
    不可变性是指每个 RDD 都是只读的,它所包含的分区信息是不可变的。由于已有的 RDD 是不可变的,所以我们只有对现有的 RDD 进行转化 (Transformation) 操作,才能得到新的 RDD ,一步一步的计算出我们想要的结果。
    这样会带来这样的好处:我们在 RDD 的计算过程中,不需要立刻去存储计算出的数据本身,我们只要记录每个 RDD 是经过哪些转化操作得来的,即:依赖关系,这样一方面可以提高计算效率,一方面是错误恢复会更加容易。如果在计算过程中,第 N 步输出的 RDD 的节点发生故障,数据丢失,那么可以根据依赖关系从第 N-1 步去重新计算出该 RDD,这也是 RDD 叫做"弹性"分布式数据集的一个原因,也会容错机制。
  3. 并行操作
    因为 RDD 的分区特性,所以其天然支持并行处理的特性。即不同节点上的数据可以分别被处理,然后生成一个新的 RDD。
    4. RDD特性考察
    下面哪个不是 RDD 的特点 (C )
    A. 可分区 B 可序列化 C 可修改 D 可持久化
    5. 惰性机制
    RDD的Transformation操作都是惰性求值的。惰性求值即当对RDD调用转化操作(例如调用map())时,操作不会立即执行。相反,Spark会在内部记录下所要求执行的操作的相关信息。
    6. 惰性机制考察
    A df.count() df.cahce() df.count()
    B df.cahce() df.count() df.count()
    A、B两个计算那个用时短?
    7. RDD和dataFrame的区别
    DataFrame 和 RDD 最大的区别 (B )
    A.科学统计支持 B.多了 schema
    C.存储方式不一样 D.外部数据源支持

二、driver、Executor相关

1. driver的功能是什么?
1)一个Spark作业运行时包括一个Driver进程,也是作业的主进程,具有main函数,并且有SparkContext的实例,是程序的人口点;
2)功能:负责向集群申请资源,向master注册信息,负责了作业的调度,负责作业的解析、生成Stage并调度Task到Executor上。
2. spark的有几种部署模式,每种模式特点?
1)本地模式:Spark不一定非要跑在hadoop集群,可以在本地,起多个线程的方式来指定。
2)Spark on yarn模式:分布式部署集群,资源和任务监控交给yarn管理,但是目前仅支持粗粒度资源分配方式,包含cluster和client运行模式,cluster适合生产,driver运行在集群子节点,具有容错功能,client适合调试,dirver运行在客户端
3)Spark On Mesos模式

三、spark存储

1. RDD持久化
Spark 中一个很重要的能力是将数据持久化(或称为缓存),在多个操作间都可以访问这些持久化的数据。当持久化一个RDD时,每个节点的其它分区都可以使用RDD在内存中进行计算,在该数据上的其他action操作将直接使用内存中的数据。这样会让以后的 action 操作计算速度加快(通常运行速度会加速 10 倍)。缓存是迭代算法和快速的交互式使用的重要工具。
RDD 可以使用 persist() 方法或 cache() 方法进行持久化。数据将会在第一次 action 操作时进行计算,并缓存在节点的内存中。Spark 的缓存具有容错机制,如果一个缓存的 RDD 的某个分区丢失了,Spark 将按照原来的计算过程,自动重新计算并进行缓存。
在 shuffle 操作中(例如 reduceByKey),即便是用户没有调用 persist 方法,Spark 也会自动缓存部分中间数据。这么做的目的是,在 shuffle 的过程中某个节点运行失败时,不需要重新计算所有的输入数据。如果用户想多次使用某个 RDD,强烈推荐在该 RDD 上调用 persist 方法。
2. Spark有几种持久化存储级别如下
1.MEMORY_ONLY:使用未序列化的Java对象格式,将数据保存在内存中。如果内存不够存放所有的数据,则数据可能就不会进行持久化。那么下次对这个RDD执行算子操作时,那些没有被持久化的数据,需要从源头处重新计算一遍。这是默认的持久化策略,使用cache()方法时,实际就是使用的这种持久化策略。
2.MEMORY_AND_DISK:使用未序列化的Java对象格式,优先尝试将数据保存在内存中。如果内存不够存放所有的数据,会将数据写入磁盘文件中,下次对这个RDD执行算子时,持久化在磁盘文件中的数据会被读取出来使用。
3.MEMORY_ONLY_SER:基本含义同MEMORY_ONLY。唯一的区别是,会将RDD中的数据进行序列化,RDD的每个partition会被序列化成一个字节数组。这种方式更加节省内存,从而可以避免持久化的数据占用过多内存导致频繁GC。
4.MEMORY_AND_DISK_SER:基本含义同MEMORY_AND_DISK。唯一的区别是,会将RDD中的数据进行序列化,RDD的每个partition会被序列化成一个字节数组。这种方式更加节省内存,从而可以避免持久化的数据占用过多内存导致频繁GC。
5.DISK_ONLY:使用未序列化的Java对象格式,将数据全部写入磁盘文件中。
6.MEMORY_ONLY_2, MEMORY_AND_DISK_2, 等等:对于上述任意一种持久化策略,如果加上后缀_2,代表的是将每个持久化的数据,都复制一份副本,并将副本保存到其他节点上。这种基于副本的持久化机制主要用于进行容错。假如某个节点挂掉,节点的内存或磁盘中的持久化数据丢失了,那么后续对RDD计算时还可以使用该数据在其他节点上的副本。如果没有副本的话,就只能将这些数据从源头处重新计算一遍了。
3. 持久化存储级别考察
默认的存储级别 (A )
A MEMORY_ONLY B MEMORY_ONLY_SER
C MEMORY_AND_DISK D MEMORY_AND_DISK_SER
下列哪个不是 RDD 的缓存方法 (C )
A persist() B Cache()
C Memory()
4. spark中cache和persist的区别

四、数据倾斜

1. 数据倾斜危害
单个或少数的节点数据量特别大,但一个 Stage 所耗费的时间,是由最慢的那个 Task 决定,所以数据倾斜会导致两个后果:

  1. OOM(单或少数的节点);
  2. 拖慢整个Job执行时间(其他已经完成的节点都在等这个还在做的节点)。
    2. 数据倾斜的现象
    当发现如下现象时,十有八九是发生数据倾斜了:
    • 绝大多数 task 执行得都非常快,但个别 task 执行极慢,整体任务卡在某个阶段不能结束。
    • 原本能够正常执行的 Spark 作业,某天突然报出 OOM(内存溢出)异常。
    3. 导致Spark数据倾斜的本质
    在进行 shuffle 的时候,必须将各个节点上相同的 key 拉取到某个节点上的一个 task 来进行处理,比如按照 key 进行聚合或 join 等操作。此时如果某个 key 对应的数据量特别大的话,就会发生数据倾斜。比如大部分 key 对应10条数据,但是个别 key 却对应了100万条数据,那么大部分 task 可能就只会分配到10条数据,然后1秒钟就运行完了;但是个别 task 可能分配到了100万数据,要运行一两个小时。
  3. 定位最慢的Task所处的源码位置
    步骤一:看数据倾斜发生在哪个stage。yarn-client模式下查看本地log或Spark Web UI中当前运行的是哪个stage;yarn-cluster模式下,通过Spark Web UI查看运行到了哪个Stage。
    主要看最慢的Stage各task分配的数据量,来确定是否是数据倾斜。
    步骤二:根据Stage划分,推算倾斜发生的代码(必然有Shuffle类算子)。
    根据stage划分原理,推算出来发生倾斜的那个stage对应代码中的哪一部分,这部分代码中肯定会有一个shuffle类算子。简单实用方法:只要看到shuffle类算子或Spark SQL的SQL语句会有Shuffle类的算子的句子,就可以知道该地方划分为前后两个Stage。(用Python的PySpark接口,Spark Web UI会查看task在源码中的行数。)
  4. 解决方案

五、宽窄依赖、Stage、Job、task

1. 谈谈spark中的宽窄依赖
依赖关系,记录了该 RDD 的计算过程,也就是说这个 RDD 是通过哪个 RDD 经过怎么样的转化操作得到的。窄依赖允许子 RDD 的每个分区可以被并行处理产生,而且支持在同一个节点上链式执行多条指令,无需等待其它父 RDD 的分区操作。
Spark 区分宽窄依赖的原因有两点:

  1. 窄依赖支持在同一节点上进行链式操作。相反,款依赖需要所有父分区都是可用的。
  2. 从失败恢复的角度考虑,窄依赖失败恢复更有效,因为只要重新计算丢失的父分区即可,而宽依赖涉及到 RDD 的各级多个父分区。
  3. 宽窄依赖考察
    下面哪个操作是窄依赖 (B )
    A join B filter
    C group D sort
    12.下面哪个操作肯定是宽依赖 (C )
    A map B flatMap
    C reduceByKey D sample
    3. Job、Stage、Task划分依据
    Job:由一个 rdd 的 action 触发的动作,当需要执行一个 rdd 的 action 的时候,会生成一个 job,一个job生成多个stage。
    Stage:stage 是一个 job 的组成单位,就是说,一个 job 会被切分成 1 个或 1 个以上的 stage,然后各个 stage 会按照执行顺序依次执行。而一个stage划分成多个tsak。
    目前有两个划分 stage 的依据:
    • 当触发 rdd 的 action 时
    • 当触发 rdd 的 shuffle 操作时
    Task:即 stage 下的一个任务执行单元,一般来说,一个 rdd 有多少个 partition,就会有多少个 task,因为每一个 task 只是处理一个 partition 上的数据。
    4. Job、Stage、Task考察
    Stage 的 Task 的数量由什么决定 (A )
    A Partition B Job C Stage D TaskScheduler

六、Spark性能优化

七、并发

八、pyspark内置函数、常用算子

1. 概述一下spark中的常用算子区别(map,mapPartitions,foreach,foreachPatition)
答:map:用于遍历RDD,将函数应用于每一个元素,返回新的RDD(transformation算子)
foreach:用于遍历RDD,将函数应用于每一个元素,无返回值(action算子)
mapPatitions:用于遍历操作RDD中的每一个分区,返回生成一个新的RDD(transformation算子)
foreachPatition:用于遍历操作RDD中的每一个分区,无返回值(action算子)
总结:一般使用mapPatitions和foreachPatition算子比map和foreach更加高效,推荐使用。

九、常见OOM类型报错,及解决办法

1、报错:启动时发现报错:java.lang.IllegalArgumentException: Required executor memory (102400+4096 MB) is above the max threshold (28672 MB) of this cluster! Please check the values of ‘yarn.scheduler.maximum-allocation-mb’ and/or ‘yarn.nodemanager.resource.memory-mb’.
原因:提交任务时,启动失败,memoryOverhead+memory > (Max)MonitorMemory。
解决: 减小两个参数的值即可。
2、报错::Driver中发现报错:YarnAllocator: Container killed by YARN for exceeding memory limits. X GB of Y GB physical memory used. Consider boosting spark.yarn.executor.memoryOverhead.
原因:运行时失败,memoryOverhead+memory > MonitorMemory
解决:通过–conf spark.sql.shuffle.partitions=XXX增大partitions个数;或增大overhead/memory的大小,不超过(Max)MonitorMemory即可。若已经到max仍然报错,可以减少单个Executor的并发数(cores),增大Executor数量。
3、报错:Excutor日志中发现报错:java.lang.OutOfMemoryError: Java heap space 、org.apache.spark.shuffle.FetchFailedException: Java heap space、 Container killed on request. Exit code is 143
原因:程序运行时所需内存 > memory。一般是因为处理数据量或者缓存的数据量较大,已有内存不足并且内存分配速度 > GC回收速度导致。
解决:增大memory、减少单个Executor的并发数(cores)、减少不必要的cache操作、尽量不要对比较大的数据做broadcast、尽量避免shuffle算子或者对程序逻辑/底层数据进行优化。
4、报错:
org.apache.spark.shuffle.FetchFailedException: java.io.FileNotFoundException: …shuffle_xxx.index (No such file or directory)
原因:OOM导致shuffle获取文件失败,此报错只是一个结果,原因是由于上述OOM导致,请详细查看日志是否有OOM的关键字。
解决:找到OOM关键字,解决OOM问题即可。 或者开启external shuffle service, --conf spark.shuffle.service.enabled=true
5、报错:
org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.ipc.StandbyException): Operation category WRITE is not supported in state standby
原因:访问(读、写)hdfs,namenode(hdfs的管理节点)较忙压力较大时,spark超过一定时间会自动切换到namenod的standby节点尝试访问。standby会返回这个异常信息,然后spark会自动连接active节点。 所以该报错只是hdfs较忙的一个提示,并不是spark运行报错。
解决:继续等待即可,或者联系集市管理人员咨询为什么hfds压力较大。
6
报错:YarnScheduler: Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient resources
ERROR FileFormatWriter: Aborting job null.
java.util.concurrent.TimeoutException: Futures timed out after [300 seconds]
原因: driver启动后提交job,超过300s(默认值)没有启动Executor会导致app超时失败
解决: 1. 调整任务执行时间,选择资源充足的时段执行。 2. 调整超时时间 --conf spark.sql.broadcastTimeout=900 (15分钟 或者其他值)

十、集群资源

  • 由于spark节点分Driver(只有一个)和Executor(一般有多个)两种概念。但两种节点内存模型一样,且OOM常发生在Executor。
  • 每个Spark Executor会单独占用一个Container,单个Container内存的上限,就是Spark Executor内存上限,后面称此值为MonitorMemory。
  • MonitorMemory = spark.yarn.executor.memoryOverhead + spark.executor.memory。我们集群中,memoryOverhead设置成固定的4G,用户也可以通过参数自己调整。
  • spark.executor.memory 需要用户自己设置。我们的集群中,建议 1 excutor core 对应 2~4G executor.memory。

十一、查看应用

yarn application

  • -list列出所有 application 信息
    示例:yarn application -list
  • -appStates跟-list一起使用,用来筛选不同状态的application,多个用","分隔;所有状态ALL,NEW,NEW_SAVING,SUBMITTED,ACCEPTED,RUNNING,FINISHED,FAILED,KILLED
    示例:yarn application -list -appStates RUNNING
  • -appTypes跟-list一起使用,用来筛选不同类型的application,多个用","分隔;如MAPREDUCE。
    示例:yarn application -list -appTypes MAPREDUCE
  • -kill杀死一个application,需要指定一个Application ID。
    示例:yarn application -kill application_1526100291229_206393
  • -status列出某个application 的状态
    示例:yarn application -status application_1526100291229_206393
  • -movetoqueue移动application到其他的queue,不能单独使用。
  • -queue与movetoqueue命令一起使用,指定移动到哪个queue。
    示例:yarn application -movetoqueue application_1526100291229_206393 -queue other

Linux

  • “|” 用来将前一个命令的标准输出传递到下一个命令的标准输入。
  • wc指令我们可以计算文件的Byte数、字数、或是列数。-l或–lines 只显示行数,-w或–words 只显示字数。
    例子:
    yarn application -list |grep *** |wc -l
    yarn application -list |grep *** |grep *** | wc -l

问题

1 显示不被截断
results.show(20, False)

你可能感兴趣的:(pyspark)