spark面试

spark面试

1:spark的算子和广播变量

算子分为Transformations转换和action行动两种算子
转换算子是懒加载的主要包括,filter,map等操作,只有行动算子才会触发执行。action算子主要包括reducebykey,foreach,print等算子,会触发真正的执行动作,只有转换算子程序会报错。
广播变量:在driver端定义的变量会分享到每个task任务。为了减小存储空间,可以使用广播变量到每个执行器executor,sc.broadcast进行定义,广播变量是在driver端定义的只读变量。

2:RDD(血统)是什么?如何创建的

RDD是只读的记录分区的数据集合,可以用于存在内存中进行共享和重复计算。RDD中的每个分区记录其中的一部分数据,然后在集群的不同的节点上通过算子进行计算。spark中的task就是一个数据分区。

RDD创建:

  • a:RDD通常通过Hadoop上的文件,即HDFS文件或者Hive表,
  • b:或者读取MQS中数据比如kafka来进行创建
  • c:有时也可以通过RDD的本地创建转换而来。
  • d:通过调用SparkContext的parallelize方法实现

RDD之间的算子操作转换会产生父RDD和子RDD之间的依赖关系,又引出来宽依赖和窄依赖的关系。

  • 宽依赖:宽依赖是产生了shuff导致的数据从一个分区分散到了不同的分区中。是指父RDD的每个分区都可能被多个子RDD分区所使用。
  • 窄依赖:窄依赖是指父RDD的每个分区只被子RDD的一个分区所使用,每个父RDD的每个分区只能到其中一个子RDD的一个分区中。比如map,filter,union等算子。
    宽依赖和窄依赖
    RDD之间的依赖关系就形成了DAG(有向无环图),图是由顶点的有穷非空集合和顶点之间边的集合组成。通过RDD间的依赖关系,可以跟踪依赖链找到该分区的父分区,重新计算该分区数据,采用这种逆推父分区,恢复数据的方式,实现了RDD的容错机制。

RDD的算子操作:

  • 算子分为Transformations转换和action行动两种算子

3:RDD持久化原理?

spark非常重要的一个功能特性就是可以将RDD持久化在内存中。

调用cache()和persist()方法即可。cache()和persist()的区别在于,cache()是persist()的一种简化方式,cache()的底层就是调用persist()的无参版本persist(MEMORY_ONLY),将数据持久化到内存中。

如果需要从内存中清除缓存,可以使用unpersist()方法。RDD持久化是可以手动选择不同的策略的。在调用persist()时传入对应的StorageLevel即可。

4:Spark作业提交流程是怎么样的

本次以yarn client模式为例。
1:spark submit 提交任务,Spark 向YARN资源管理器的ResourceManager(负责集群的资源分配)申请启动Application Master(yarn中的角色)同时执行初始化SparkContext,此时会在driver端构造DAGScheduler 和 TaskScheduler两种调度器。
2:ResourceManager收到请求后,在集群中选择一个NodeManager,为该应用程序分配第一个Container(client模式是提交任务的服务器,在ui界面可以看到),要求它在这个Container中启动应用程序的ApplicationMaster
与YARN-Cluster区别的是在该ApplicationMaster不运行SparkContext,只与SparkContext进行联系和资源的分派;
3:APP master启动后根据任务信息向ResourceManager申请运行资源,然后把申请到的资源发送到各对应worker上去启动executor,并把executor向driver端反向注册,driver端创建线程池维护所有的executor信息;

4:全部executor注册后,sparkcontext初始化完成。
5:完成后会继续执行我们提交的App的代码,当触发了Action的RDD算子时,就触发了一个job,这时就会调用DAGScheduler从后往前把job进行Stage划分形成DAG有向无环图(stage划分在driver端运行);
6:将划分好的Stage封装到TaskSet对象,然后TaskSet提交到TaskScheduler。
7:TaskScheduler:维护所有TaskSet,分发Task给各个节点的Executor上根据数据本地化策略分发Task),监控task的运行状态,负责重试失败的task;
8:task运行完成后,SparkContext向Master注销,释放资源进行下次计算;

5:spark优化

5.1:算子调优

1:使用高性能算子

使用reduceByKey替代groupByKey
使用mapPartitions替代普通map。mapPartitions类的算子,一次函数调用会处理一个partition所有的数据
使用foreachPartitions替代foreach:一次处理一个分区数据
使用filter之后进行coalesce操作,减少rdd的分区

2:对重复使用的rdd进行持久化并选择持久化级别,RDD调用cache()和persist()即可。
3:避免使用reduce等shuffle类算子减少数据传输

5.2:资源调优

根据spark ui界面的gc时间,调优计算资源。executor-cores,executor-memory等

6:spark数据倾斜

1:现象:spark ui界面中某个task运行时间特别长或者程序某天报oom,因为某个task分配了过多的数据,缓慢的任务会拖垮整个程序的运行速度
2:数据倾斜的原因
包括数据问题和spark使用问题
数据问题

  • 1、key本身分布不均衡(包括大量的key为空)
  • 2、key的设置不合理

spark使用问题

  • 1、shuffle时的并发度不够

3:倾斜解决

1:shuffle类算子导致的task数据倾斜,提高shuffle的并行度,默认200。
2:如果是大小数据集join导致的。可以将小数据集通过广播变量 广播出去,再对大的数据集执行map操作避免shuffle操作,避免了数据倾斜
3:大表join的话可以通过给倾斜的key加随机数前缀或者后缀的方式加盐处理,保证join正常

7、谈谈spark中的宽窄依赖

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

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

8、spark和MapReduce的对比

1、spark处理数据是基于内存的,所以性能更高。而MapReduce是基于磁盘处理数据的。
2、Spark在处理数据时构建了DAG有向无环图,中间rdd的执行结果存在内存而不再需要读写HDFS,减少大量的磁盘io。减少了shuffle和数据落地磁盘的次数
3、spark供了抽象的数据集(RDD、Dataset、DataFrame、DStream)有高度封装的API,使用更方便
4、Spark是粗粒度资源申请,而MapReduce是细粒度资源申请

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值