spark常见面试题

1、spark中的RDD是什么,有哪些特性

RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合。

Dataset:就是一个集合,用于存放数据的

Distributed:分布式,可以并行在集群计算

Resilient:表示弹性的

弹性表示

1、RDD中的数据可以存储在内存或者是磁盘

2、RDD中的分区是可以改变的

五大特性:

A list of partitions

一个分区列表,RDD中的数据都存在一个分区列表里面

A function for computing each split

作用在每一个分区中的函数

A list of dependencies on other RDDs

一个RDD依赖于其他多个RDD,这个点很重要,RDD的容错机制就是依据这个特性而来的

Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)

可选的,针对于kv类型的RDD才具有这个特性,作用是决定了数据的来源以及数据处理后的去向

Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)

可选项,数据本地性,数据位置最优

2、概述一下spark中的常用算子区别(map、mapPartitions、foreach、foreachPartition) map:用于遍历RDD,将函数f应用于每一个元素,返回新的RDD(transformation算子)。

foreach:用于遍历RDD,将函数f应用于每一个元素,无返回值(action算子)。

mapPartitions:用于遍历操作RDD中的每一个分区,返回生成一个新的RDD(transformation算子)。

foreachPartition: 用于遍历操作RDD中的每一个分区。无返回值(action算子)。

总结:一般使用mapPartitions或者foreachPartition算子比map和foreach更加高效,推荐使用。

3、谈谈spark中的宽窄依赖

RDD和它依赖的父RDD(s)的关系有两种不同的类型,即窄依赖(narrow dependency)和宽依赖(wide dependency)。

宽依赖:指的是多个子RDD的Partition会依赖同一个父RDD的Partition

指子RDD的分区依赖于父RDD的所有分区,这是因为shuffle类操作,如图中的groupByKey和未经协同划分的join。

窄依赖:指的是每一个父RDD的Partition最多被子RDD的一个Partition使用。

指父RDD的每一个分区最多被一个子RDD的分区所用,表现为一个父RDD的分区对应于一个子RDD的分区,和两个父RDD的分区对应于一个子RDD 的分区。图中,map/filter和union属于第一类,对输入进行协同划分(co-partitioned)的join属于第二类。

4、spark中如何划分stage

rdd当中dag的划分

dag叫做有向无环图,rdd之间一系列的转换,就形成了DAG,dag的主要作用,就是用来划分stage的,

stage叫做一个个的阶段,通过划分stage可以得到taskSet

stage的划分:从最后一个rdd,往前划,遇到窄依赖,加入当前stage,遇到宽依赖,划开一个stage

Stage划分思路

因此spark划分stage的整体思路是:从后往前推,遇到宽依赖就断开,划分为一个stage;遇到窄依赖就将这个RDD加入该stage中。因此在图2中RDD C,RDD D,RDD E,RDDF被构建在一个stage中,RDD A被构建在一个单独的Stage中,而RDD B和RDD G又被构建在同一个stage中。
  在spark中,Task的类型分为2种:ShuffleMapTask和ResultTask;简单来说,DAG的最后一个阶段会为每个结果的partition生成一个ResultTask,即每个Stage里面的Task的数量是由该Stage中最后一个RDD的Partition的数量所决定的!而其余所有阶段都会生成ShuffleMapTask;之所以称之为ShuffleMapTask是因为它需要将自己的计算结果通过shuffle到下一个stage中;也就是说图2中的stage1和stage2相当于mapreduce中的Mapper,而ResultTask所代表的stage3就相当于mapreduce中的reducer。

总结:map,filtre为窄依赖, groupbykey为宽依赖 ,遇到一个宽依赖就分一个stage

5、spark-submit的时候如何引入外部jar包

在通过spark-submit提交任务时,可以通过添加配置参数来指定

–driver-class-path 外部jar包

–jars 外部jar包

6、spark 如何防止内存溢出

driver端的内存溢出

可以增大driver的内存参数:spark.driver.memory (default 1g)

这个参数用来设置Driver的内存。在Spark程序中,SparkContext,DAGScheduler都是运行在Driver端的。对应rdd的Stage切分也是在Driver端运行,如果用户自己写的程序有过多的步骤,切分出过多的Stage,这部分信息消耗的是Driver的内存,这个时候就需要调大Driver的内存。

map过程产生大量对象导致内存溢出

这种溢出的原因是在单个map中产生了大量的对象导致的,例如:rdd.map(x=>for(i <- 1 to 10000) yield i.toString),这个操作在rdd中,每个对象都产生了10000个对象,这肯定很容易产生内存溢出的问题。针对这种问题,在不增加内存的情况下,可以通过减少每个Task的大小,以便达到每个Task即使产生大量的对象Executor的内存也能够装得下。具体做法可以在会产生大量对象的map操作之前调用repartition方法,分区成更小的块传入map。例如:rdd.repartition(10000).map(x=>for(i <- 1 to 10000) yield i.toString)。

面对这种问题注意,不能使用rdd.coalesce方法,这个方法只能减少分区,不能增加分区,不会有shuffle的过程。

数据不平衡导致内存溢出

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值