Q1、 Spark job的运行架构?
1、构建Spark Application 的运行环境(初始化SparkContext), SparkContext向资源管理器(可以是Standalone、Mesos或YARN)注册并申请运行Executor资源
2、资源管理器分配 Executor 资源并启动 StandaloneExecutorBackend,Executor 运行情况将随着心跳发送到资源管理器上
3、 SparkContext构建成DAG 图,将DAG 图分解成Stage,并把Taskset发送给TaskScheduler。Executor 向 SparkContext 申请 Task,TaskScheduler 将 Task 发放给 Executor 运行同时SparkContext将应用程序代码发放Executor
4、Task在 Executor上运行,运行完毕释放所有资源。
Q2、 Spark有几种运行模式
4种:standalone模式,Local模式,Spark on YARN 模式,mesos模式
Q3、 Spark如何指定本地模式
在IDEA,Eclipse里面开发的模式就是Local模式。还有,我们直接用Spark-Shell这种进来的模式也是local。
new SparkConf().setMaster(“local”),这时候我们默认的分区数 = 你的本台服务器的CPU core的个数。
分区数 = task 的个数
new SparkConf().setMasater(“local[N]”) 这个时候分区的个数 = N
Q4、 Spark的算子分类
1)Transformation 变换/转换算子:这种变换并不触发提交作业,完成作业中间过程处理。
Transformation 操作是延迟计算的,也就是说从一个RDD 转换生成另一个 RDD 的转换操作不是马上执行,需要等到有 Action 操作的时候才会真正触发运算。
2)Action 行动算子:这类算子会触发 SparkContext 提交 Job 作业。
Action 算子会触发 Spark 提交作业(Job),并将数据输出 Spark系统。
Q5、 Spark中stage的划分规则
Spark任务会根据RDD之间的依赖关系,形成一个DAG有向无环图,DAG会提交给DAGScheduler,DAGScheduler会把DAG划分相互依赖的多个stage,划分stage的依据就是RDD之间的宽窄依赖。遇到宽依赖就划分stage,每个stage包含一个或多个task任务。然后将这些task以taskSet的形式提交给TaskScheduler运行。stage是由一组并行的task组成。
Q6、 如何区分spark哪些操作是shuffle操作
Shuffle是划分DAG中stage的标识,同时影响spark执行速度的关键步骤。宽依赖会发生shuffle操作。RDD的Transformtion函数中,又分为窄依赖和宽依赖的操作。窄依赖跟宽依赖的区别是是否发生shuffle操作。窄依赖是子RDD的各个分片不依赖于其他分片,能够独立计算得到结果,宽依赖指子RDD的各个分片会依赖于父RDD的多个分片,会造成父RDD分各个分片在集群中重新分片。
Q7、 RDD,DataFrame,DataSet的区别
DataFrame比RDD多了数据的结构信息,即schema。RDD是分布式的 Java对象的集合。DataFrame是分布式的Row对象的集合。DataFrame除了提供了比RDD更丰富的算子以外,更重要的特点是提升执行效率、减少数据读取以及执行计划的优化;Dataset可以认为是DataFrame的一个特例,主要区别是Dataset每一个record存储的是一个强类型值而不是一个Row
Q8、 解释一下DAG
DAG,有向无环图,每个操作生成的RDD之间都会连一条线,最后组成的有向无环图
Q9、 map和flatmap的区别
map函数会对每一条输入进行指定的操作,然后为每一条输入返回一个对象;而flatMap函数则是两个操作–先映射后扁平化:同map函数一样:对每一条输入进行指定的操作,然后为每一条输入返回一个对象,最后将所有对象合并为一个对象。
Q10、 spark中rdd.persist()和rdd.cache()的区别
1)RDD的cache()方法其实调用的就是persist方法,缓存策略均为MEMORY_ONLY;
2)可以通过persist方法手工设定StorageLevel来满足工程需要的存储级别;
3)cache或者persist并不是action;
Q11、 spark如何提交脚本
Spark提供了一个容易上手的应用程序部署工具bin/spark-submit,可以完成Spark应用程序在local、Standalone、YARN、Mesos上的快捷部署。可以指定集群资源master,executor/ driver的内存资源等。
Q12、 spark内存不足怎么处理?
1.在不增加内存的情况下,可以通过减少每个Task的大小
2.在shuffle的使用,需要传入一个partitioner,通过设置 spark.default.parallelism参数3.在standalone的模式下如果配置了–total-executor-cores 和 --executor-memory 这两个参数外,还需要同时配置–executor-cores或者spark.executor.cores参数,确保Executor资源分配均匀。
4.如果RDD中有大量的重复数据,或者Array中需要存大量重复数据的时候我们都可以将重复数据转化为String,能够有效的减少内存使用
Q13、 mapreduce和spark计算框架效率区别的原因
spark是借鉴了Mapreduce,并在其基础上发展起来的,继承了其分布式计算的优点并进行了改进,spark生态更为丰富,功能更为强大,性能更加适用范围广,mapreduce更简单,稳定性好。主要区别
(1)spark把运算的中间数据存放在内存,迭代计算效率更高,mapreduce的中间结果需要落地,保存到磁盘
(2)Spark容错性高,它通过弹性分布式数据集RDD来实现高效容错,RDD是一组分布式的存储在节点内存中的只读性的数据集,这些集合石弹性的,某一部分丢失或者出错,可以通过整个数据集的计算流程的血缘关系来实现重建,mapreduce的容错只能重新计算
(3)Spark更通用,提供了transformation和action这两大类的多功能api,另外还有流式处理sparkstreaming模块、图计算等等,mapreduce只提供了map和reduce两种操作,流计算及其他的模块支持比较缺乏。
(4)Spark框架和生态更为复杂,有RDD,血缘lineage、执行时的有向无环图DAG,stage划分等,很多时候spark作业都需要根据不同业务场景的需要进行调优以达到性能要求,mapreduce框架及其生态相对较为简单,对性能的要求也相对较弱,运行较为稳定,适合长期后台运行。
Q14、 Spark数据倾斜怎么处理?
https://tech.meituan.com/spark_tuning_pro.html
Q15、 Spark如何和kafka对接?
1、 KafkaUtils.createStream
执行流程如下:
创建createStream,Receiver被调起执行
连接ZooKeeper,读取相应的Consumer、Topic配置信息等
通过consumerConnector连接到Kafka集群,收取指定topic的数据
创建KafkaMessageHandler线程池来对数据进行处理,通过ReceiverInputDStream中的方法,将数据转换成BlockRDD,供后续计算
2、 KafkaUtils.createDirectStream
执行流程如下:
实例化KafkaCluster,根据用户配置的Kafka参数,连接Kafka集群
通过Kafka API读取Topic中每个Partition最后一次读的Offset
接收成功的数据,直接转换成KafkaRDD,供后续计算
二者区别?:
1.简化的并行:在Receiver的方式中是通过创建多个Receiver之后利用union来合并成一个Dstream的方式提高数据传输并行度。而在Direct方式中,Kafka中的partition与RDD中的partition是一一对应的并行读取Kafka数据,这种映射关系也更利于理解和优化。
2.高效:在Receiver的方式中,为了达到0数据丢失需要将数据存入Write Ahead Log中,这样在Kafka和日志中就保存了两份数据,浪费!而第二种方式不存在这个问题,只要我们Kafka的数据保留时间足够长,我们都能够从Kafka进行数据恢复。
3.精确一次:在Receiver的方式中,使用的是Kafka的高阶API接口从Zookeeper中获取offset值,这也是传统的从Kafka中读取数据的方式,但由于Spark Streaming消费的数据和Zookeeper中记录的offset不同步,这种方式偶尔会造成数据重复消费。而第二种方式,直接使用了简单的低阶Kafka API,Offsets则利用Spark Streaming的checkpoints进行记录,消除了这种不一致性。
Q16、 Spark如何和mysql对接?
实例化Properties,调用put方法,根据用户配置的mysql的参数填写put方法的参数,编写jdbc的链接的URL的信息,使用实例化的SQLContext调用read的jbdc方法,生成一个DataFrame ,供后续计算
Q17、 Sparkstreaming数据写入mysql用的什么算子?为什么不用mappartition?
forearchpartition中建立数据库连接:这样一个partition,只需连接一次外部存储。性能上有大幅度的提高,一个partition共享连接,还有重要的一点就是partition中传入的参数是整个partition数据的迭代器。
mappartition该函数只适用于元素为KV对的RDD。
Q18、 用过spark和kafka组合吗?Spark阻塞了,是什么原因导致的?
spark streaming虽然是按照时间片消费数据的,但是上一个批次的数据没有处理完,下一个批次也会继续处理,如果有很多批次的数据同时在处理。会拖垮集群,服务器的资源会使用频繁,导致很慢,甚至任务阻塞。
看看时间片是否过小,最小的时间间隔,参考在0.5~2秒钟之间。可以适当放宽时间片的大小。
Q19、 storm与sparkstraming的优缺点
1.Storm是纯实时的,Spark Streaming是准实时的
2.Storm的事务机制、健壮性、容错性、动态调整并行度特性,都要比Spark Streaming更加的优秀
3.但是SparkStream, 有一点是Storm绝对比不上的,就是:它位于Spark生态技术中,因此Spark Streaming可以和Spark Core、Spark SQL无缝集合,也就意味这,我们可以对实时处理出来的数据,立刻进行程序中无缝的延迟批处理,交互式查询等条件操作
Q20、 Scala隐式转换
Scala中的隐式转换是一种非常强大的代码查找机制。当函数、构造器调用缺少参数时或者某一实例调用了其他类型的方法导致编译不通过时,编译器会尝试搜索一些特定的区域,尝试使编译通过。
触发时机:
1)当一个对象去调用某个方法的时候,不具备这个方法
2)当某个对象去调用某个方法,但是传入的参数类型不匹配
3)A <% B // <% 是把A类型转化成B类型的意思
A必须是B的子类,但是如果A如果不是B的子类,那么这个时候会触发隐式转换,把A变为B的类型
①在Scala当中,要想使用隐式转换,必须标记为implicit关键字,implicit关键字可以用来修饰参数(隐式值与隐式参数)、函数(隐式视图)、类(隐式类)、对象(隐式对象).
②隐式转换在整个作用域中,必须是单一的标识符,进而避免隐式冲突.
③在隐式转换的作用域查找中,如果当前作用域没有隐式转换,编译器就会自动到相应源或目标类型的伴生对象中查找隐式转换。
④Scala中的隐式值、隐式类、隐式对象常放在单例对象object中.
Q21、 Scala高级函数
可以使用其他函数作为参数,或者使用函数作为输出结果,会自动类型推断,比如 map、foreach
Q22、 Spark整合Hive
1.添加对应jar包依赖
2.集群上启动 hivesever2 服务
nohup hiveserver2 1>/dev/null 2>/dev/null &
或者 metastore 服务
metastore需要添加如下配置:
hive.metastore.uris
thrift://hadoop4:9083
开启服务:nohup hive --service metastore 1>/dev/null 2>/dev/null &
3.将hive-site.xml放进classpath
4.sparkSession=SparkSession.builder().master(“local”).appName(“testhive”).enableHiveSupport().getOrCreate() //一定要调用一下enableHiveSupport()