一、Spark

1.1 Spark有几种部署形式?请别离简要阐述

  • 1)Local:运行在一台机器上,通常是练手或者测试环境。
  • 2)Standalone:构建一个基于Mster+Slaves的资源调度集群,Spark工作提交给Master运行。是Spark本身的一个调度零碎。
  • 3)Yarn: Spark客户端间接连贯Yarn,不须要额定构建Spark集群。有yarn-client和yarn-cluster两种模式,次要区别在于:Driver程序的运行节点。
  • 4)Mesos:国内大环境比拟少用。

1.2 Spark工作应用什么进行提交,javaEE界面还是脚本

Shell 脚本。

1.3 Spark提交作业参数(重点)

1)在提交工作时的几个重要参数

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

2)边给一个提交工作的款式

spark-submit \  --master local\[5\]  \  --driver-cores 2   \  --driver-memory 8g \  --executor-cores 4 \  --num-executors 10 \  --executor-memory 8g \  --class PackageName.ClassName XXXX.jar \  --name "Spark Job Name" \  InputPath      \  OutputPath

1.4 简述Spark的架构与作业提交流程(画图解说,注明各个局部的作用)(重点)

参考: https://blog.csdn.net/wuxintd...

1.4.1、standlone

1.4.2、yarn-cluster

1.5 如何了解Spark中的血统概念(RDD)(口试重点)

参考:https://blog.csdn.net/wuxintd...

  RDDLineage依赖方面分为两种Narrow DependenciesWide Dependencies用来解决数据容错时的高效性以及划分工作时候起到重要作用。

1.6 简述Spark的宽窄依赖,以及Spark如何划分stage,每个stage又依据什么决定task个数? (口试重点)

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

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

1.7 请列举Spark的transformation算子(不少于8个),并简述性能(重点)

参考: https://blog.csdn.net/wuxintd...

1)map(func):返回一个新的RDD,该RDD由每一个输出元素通过func函数转换后组成.

2)mapPartitions(func):相似于map,但独立地在RDD的每一个分片上运行,因而在类型为T的RD上运行时,func的函数类型必须是Iterator[T] => Iterator[U]。假如有N个元素,有M个分区,那么map的函数的将被调用N次,而mapPartitions被调用M次,一个函数一次解决所有分区。

3)reduceByKey(func,[numTask]):在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,应用定的reduce函数,将雷同key的值聚合到一起,reduce工作的个数能够通过第二个可选的参数来设置。

4)aggregateByKey (zeroValue:U,[partitioner: Partitioner]) (seqOp: (U, V) => U,combOp: (U, U) => U: 在kv对的RDD中,,按key将value进行分组合并,合并时,将每个value和初始值作为seq函数的参数,进行计算,返回的后果作为一个新的kv对,而后再将后果依照key进行合并,最初将每个分组的value传递给combine函数进行计算(先将前两个value进行计算,将返回后果和下一个value传给combine函数,以此类推),将key与计算结果作为一个新的kv对输入。

5)combineByKey(createCombiner: V=>C, mergeValue: (C, V) =>C, mergeCombiners: (C, C) =>C):

对雷同K,把V合并成一个汇合。

1.createCombiner: combineByKey() 会遍历分区中的所有元素,因而每个元素的键要么还没有遇到过,要么就和之前的某个元素的键雷同。如果这是一个新的元素,combineByKey()会应用一个叫作createCombiner()的函数来创立那个键对应的累加器的初始值

2.mergeValue: 如果这是一个在解决以后分区之前曾经遇到的键,它会应用mergeValue()办法将该键的累加器对应的以后值与这个新的值进行合并

3.mergeCombiners: 因为每个分区都是独立解决的, 因而对于同一个键能够有多个累加器。如果有两个或者更多的分区都有对应同一个键的累加器, 就须要应用用户提供的 mergeCombiners() 办法将各个分区的后果进行合并。

依据本身状况抉择比拟相熟的算子加以介绍。

1.8 请列举Spark的action算子(不少于6个),并简述性能(重点)

参考: https://blog.csdn.net/wuxintd...

1)reduce:

2)collect:

3)first:

4)take:

5)aggregate:

6)countByKey:

7)foreach:

8)saveAsTextFile:

1.9 请列举会引起Shuffle过程的Spark算子,并简述性能。

reduceBykey:

groupByKey:

ByKey:

1.10 简述Spark的两种外围Shuffle(HashShuffle与SortShuffle)的工作流程(包含未优化的HashShuffle、优化的HashShuffle、一般的SortShuffle与bypass的SortShuffle)(重点)

未经优化的HashShuffle:

优化后的Shuffle:

一般的SortShuffle:

shuffle read task 的 数 量 小 于 等 于 spark.shuffle.sort

bypassMergeThreshold 参数的值时(默认为 200),就会启用 bypass 机制

1.11 Spark罕用算子reduceByKey与groupByKey的区别,哪一种更具劣势?(重点)

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

groupByKey:依照key进行分组,间接进行shuffle。

开发领导:reduceByKey比groupByKey,倡议应用。然而须要留神是否会影响业务逻辑。

1.12 Repartition和Coalesce关系与区别

1)关系:

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

2)区别:

repartition肯定会产生shuffle,coalesce依据传入的参数来判断是否产生shuffle

个别状况下

  • 增大rdd的partition数量应用repartition
  • 缩小partition数量时应用coalesce

1.13 别离简述Spark中的缓存机制(cache和persist)与checkpoint机制,并指出两者的区别与分割

都是做RDD长久化的

cache:内存,不会截断血缘关系,应用计算过程中的数据缓存。

checkpoint:磁盘,截断血缘关系,在ck之前必须没有任何工作提交才会失效,ck过程会额定提交一次工作。

1.14 简述Spark中共享变量(播送变量和累加器)的基本原理与用处。(重点)

  累加器(accumulator)是Spark中提供的一种分布式的变量机制,其原理相似于mapreduce,即分布式的扭转,而后聚合这些扭转。累加器的一个常见用处是在调试时对作业执行过程中的事件进行计数。而播送变量用来高效散发较大的对象。

  共享变量呈现的起因:

  通常在向 Spark 传递函数时,比方应用 map() 函数或者用 filter() 传条件时,能够应用驱动器程序中定义的变量,然而集群中运行的每个工作都会失去这些变量的一份新的正本,更新这些正本的值也不会影响驱动器中的对应变量。

  Spark的两个共享变量,累加器与播送变量,别离为后果聚合与播送这两种常见的通信模式冲破了这一限度。

1.15 当Spark波及到数据库的操作时,如何缩小Spark运行中的数据库连接数?

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

1.16 简述SparkSQL中RDD、DataFrame、DataSet三者的区别与分割? (口试重点)

1)RDD

长处:

  • 编译时类型平安
  • 编译时就能查看出类型谬误
  • 面向对象的编程格调
  • 间接通过类名点的形式来操作数据

毛病:

  • 序列化和反序列化的性能开销
  • 无论是集群间的通信, 还是IO操作都须要对对象的构造和数据进行序列化和反序列化。
  • GC的性能开销,频繁的创立和销毁对象, 势必会减少GC

2)DataFrame

DataFrame引入了schemaoff-heap

schema : RDD每一行的数据, 构造都是一样的,这个构造就存储在schema中。 Spark通过schema就可能读懂数据, 因而在通信和IO时就只须要序列化和反序列化数据, 而构造的局部就能够省略了。

3)DataSet

DataSet联合了RDD和DataFrame的长处,并带来的一个新的概念Encoder

当序列化数据时,Encoder产生字节码与off-heap进行交互,可能达到按需拜访数据的成果,而不必反序列化整个对象。Spark还没有提供自定义Encoder的API,然而将来会退出。

三者之间的转换:

1.17 SparkSQL中join操作与left join操作的区别?

  join和sql中的inner join操作很类似,返回后果是后面一个汇合和前面一个汇合中匹配胜利的,过滤掉关联不上的。

  leftJoin相似于SQL中的左外关联left outer join,返回后果以第一个RDD为主,关联不上的记录为空。

  局部场景下能够应用left semi join代替left join:

  因为 left semi join 是 in(keySet) 的关系,遇到右表重复记录,左表会跳过,性能更高,而 left join 则会始终遍历。然而left semi join 中最初 select 的后果中只许呈现左表中的列名,因为右表只有 join key 参加关联计算了

1.18 请手写出wordcount的Spark代码实现(Scala)(手写代码重点)

 val conf: SparkConf = new SparkConf().setMaster("local\[*\]").setAppName("WordCount") val sc = new SparkContext(conf) sc.textFile("/input").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).saveAsTextFile("/output") sc.stop()

1.19、 如何应用Spark实现topN的获取(形容思路或应用伪代码)(重点)

办法1:

  • (1)依照key对数据进行聚合(groupByKey)
  • (2)将value转换为数组,利用scala的sortBy或者sortWith进行排序(mapValues)数据量太大,会OOM。

办法2:

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

办法3:

  • (1)自定义分区器,依照key进行分区,使不同的key进到不同的分区
  • (2)对每个分区使用spark的排序算子进行排序

1.20 京东:调优之前与调优之后性能的具体比照(例如调整map个数,map个数之前多少、之后多少,有什么晋升)

  这里举个例子。比方咱们有几百个文件,会有几百个map呈现,读取之后进行join操作,会十分的慢。这个时候咱们能够进行coalesce操作,比方240个map,咱们合成60个map,也就是窄依赖。这样再shuffle,过程产生的文件数会大大减少。进步join的工夫性能。

二、SparkStreaming

参考: https://chbxw.blog.csdn.net/a...

2.1、 SparkStreaming有哪几种形式生产Kafka中的数据,它们之间的区别是什么?

1、基于Receiver的形式

  这种形式应用Receiver来获取数据。Receiver是应用Kafka的高层次Consumer API来实现的。receiver从Kafka中获取的数据都是存储在Spark Executor的内存中的(如果忽然数据暴增,大量batch沉积,很容易呈现内存溢出的问题),而后Spark Streaming启动的job会去解决那些数据。

  然而,在默认的配置下,这种形式可能会因为底层的失败而失落数据。如果要启用高牢靠机制,让数据零失落,就必须启用Spark Streaming的预写日志机制(Write Ahead Log,WAL)。该机制会同步地将接管到的Kafka数据写入分布式文件系统(比方HDFS)上的预写日志中。所以,即便底层节点呈现了失败,也能够应用预写日志中的数据进行复原。

2、基于Direct的形式

  这种新的不基于Receiver的间接形式,是在Spark 1.3中引入的,从而可能确保更加强壮的机制。代替掉应用Receiver来接收数据后,这种形式会周期性地查问Kafka,来取得每个topic+partition的最新的offset,从而定义每个batch的offset的范畴。当解决数据的job启动时,就会应用Kafka的简略consumer api来获取Kafka指定offset范畴的数据。

长处如下

   简化并行读取:如果要读取多个partition,不须要创立多个输出DStream而后对它们进行union操作。Spark会创立跟Kafka partition一样多的RDD partition,并且会并行从Kafka中读取数据。所以在Kafka partition和RDD partition之间,有一个一对一的映射关系。

  高性能:如果要保障零数据失落,在基于receiver的形式中,须要开启WAL机制。这种形式其实效率低下,因为数据实际上被复制了两份,Kafka本人自身就有高牢靠的机制,会对数据复制一份,而这里又会复制一份到WAL中。而基于direct的形式,不依赖Receiver,不须要开启WAL机制,只有Kafka中作了数据的复制,那么就能够通过Kafka的正本进行复原。

  一次且仅一次的事务机制

3、比照:

  基于receiver的形式,是应用Kafka的高阶API来在ZooKeeper中保留生产过的offset的。这是生产Kafka数据的传统形式。这种形式配合着WAL机制能够保证数据零失落的高可靠性,然而却无奈保证数据被解决一次且仅一次,可能会解决两次。因为Spark和ZooKeeper之间可能是不同步的。

  基于direct的形式,应用kafka的简略api,Spark Streaming本人就负责追踪生产的offset,并保留在checkpoint中。Spark本人肯定是同步的,因而能够保证数据是生产一次且仅生产一次。

  在理论生产环境中大都用Direct形式

2.2 简述SparkStreaming窗口函数的原理(重点)

   窗口函数就是在原来定义的SparkStreaming计算批次大小的根底上再次进行封装,每次计算多个批次的数据,同时还须要传递一个滑动步长的参数,用来设置当次计算工作实现之后下一次从什么中央开始计算。

  图中time1就是SparkStreaming计算批次大小,虚线框以及实线大框就是窗口的大小,必须为批次的整数倍。虚线框到大实线框的间隔(相隔多少批次),就是滑动步长。

三、SparkSQL

关注我的公众号【宝哥大数据】,更多干货