spark简介
Spark是一种由Scala语言开发的快速、通用、可扩展的大数据分析引擎
Spark Core中提供了Spark最基础与最核心的功能
Spark SQL是Spark用来操作结构化数据的组件。通过Spark SQL,用户可以使用SQL或者Apache Hive版本的SQL方言(HQL)来查询数据。
Spark Streaming是Spark平台上针对实时数据进行流式计算的组件,提供了丰富的处理数据流的API。
Spark主要功能主要是用于数据计算,所以其实Spark一直被认为是Hadoop MR框架的升级版
1、spark介绍
Spark是一种由Scala语言开发的快速、通用、可扩展的大数据分析引擎,Spark主要功能主要是用于数据计算,所以其实Spark一直被认为是Hadoop MR框架的升级版
2、RDD的缺点和优点
- 自动进行内存和磁盘切换
- 基于lineage的高效容错
- task如果失败,会特定次数的重试
- 数据调度弹性:DAG TASK和资源管理无关
3、Spark和Hadoop的对比
A:Spark的中间数据放到内存中,对于迭代运算效率更高。Spark更适合于迭代运算比较多的ML和DM运算。因为在Spark里面,有RDD的抽象概念。所以,Spark比Hadoop更通用
4、哪些spark算子会有shuffle?
- 去重,distinct
- 排序,groupByKey,reduceByKey等
- 重分区,repartition,coalesce
- 集合或者表操作,interection,join
5、Spark stage是如何划分的?
- 从hdfs中读取文件后,创建 RDD 对象
- DAGScheduler模块介入运算,计算RDD之间的依赖关系。RDD之间的依赖关系就形成了DAG
- 每一个JOB被分为多个Stage,划分Stage的一个主要依据是当前计算因子的输入是否是确定的,如果是则将其分在同一个Stage,避免多个Stage之间的消息传递开销。
因此spark划分stage的整体思路是:从后往前推,遇到宽依赖就断开,划分为一个stage;遇到窄依赖就将这个RDD加入该stage中。
图解:
6、Spark有哪些聚合类的算子,我们应该尽量避免什么类型的算子?
在我们的开发过程中,能避免则尽可能避免使用reduceByKey、join、distinct、repartition等会进行shuffle的算子,尽量使用map类的非shuffle算子。这样的话,没有shuffle操作或者仅有较少shuffle操作的Spark作业,可以大大减少性能开销。
7、你所理解的Spark的shuffle过程?
首先每一个Mapper会根据Reducer的数量创建出相应的bucket,bucket的数量是MM×RR,其中MM是Map的个数,RR是Reduce的个数。
其次Mapper产生的结果会根据设置的partition算法填充到每个bucket中去。这里的partition算法是可以自定义的,当然默认的算法是根据key哈希到不同的bucket中去。
当Reducer启动时,它会根据自己task的id和所依赖的Mapper的id从远端或是本地的block manager中取得相应的bucket作为Reducer的输入进行处理。
8、对于Spark中的数据倾斜问题,你有什么好的方案?
1、前提是定位数据倾斜,是OOM了,还是任务执行缓慢,看日志,看WebUI
2、解决方法,有多个方面
-
避免不必要的shuffle,如使用广播小表的方式,将reduce-side-join提升为map-side-join
-
分拆发生数据倾斜的记录,分成几个部分进行,然后合并join后的结果
-
改变并行度,可能并行度太少了,导致个别task数据压力大
-
两阶段聚合,先局部聚合,再全局聚合
-
自定义paritioner,分散key的分布,使其更加均匀
9、Spark为什么要持久化,一般什么场景下要进行persist操作?
为什么要进行持久化?
spark所有复杂一点的算法都会有persist身影,spark默认数据放在内存,spark很多内容都是放在内存的,非常适合高速迭代,1000个步骤
只有第一个输入数据,中间不产生临时数据,但分布式系统风险很高,所以容易出错,就要容错,rdd出错或者分片可以根据血统算出来,如果没有对父rdd进行persist 或者cache的化,就需要重头做。
以下场景会使用persist
1)某个步骤计算非常耗时,需要进行persist持久化
2)计算链条非常长,重新恢复要算很多步骤,很好使,persist
3)checkpoint所在的rdd要持久化persist,
lazy级别,框架发现有checnkpoint,checkpoint时单独触发一个job,需要重算一遍,checkpoint前
要持久化,写个rdd.cache或者rdd.persist,将结果保存起来,再写checkpoint操作,这样执行起来会非常快,不需要重新计算rdd链条了。checkpoint之前一定会进行persist。
4)shuffle之后为什么要persist,shuffle要进性网络传输,风险很大,数据丢失重来,恢复代价很大
5)shuffle之前进行persist,框架默认将数据持久化到磁盘,这个是框架自动做的。
10、介绍一下join操作优化经验?
join其实常见的就分为两类: map-side join 和 reduce-side join。当大表和小表join时,用map-side join能显著提高效率。将多份数据进行关联是数据处理过程中非常普遍的用法,不过在分布式计算系统中,这个问题往往会变的非常麻烦,因为框架提供的 join 操作一般会将所有数据根据 key 发送到所有的 reduce 分区中去,也就是 shuffle 的过程。造成大量的网络以及磁盘IO消耗,运行效率极其低下,这个过程一般被称为 reduce-side-join。如果其中有张表较小的话,我们则可以自己实现在 map 端实现数据关联,跳过大量数据进行 shuffle 的过程,运行时间得到大量缩短,根据不同数据可能会有几倍到数十倍的性能提升。