1 问题分析
Spark是基于内存的,而MapReduce是基于磁盘的迭代。
2 核心答案讲解:
1、Spark是基于内存进行数据处理的,MapReduce是基于磁盘进行数据处理的。
中间结果保存在文件中,提高了可靠性,减少了内存占用,但是牺牲了性能。
数据在内存中进行交换,要快一些,但是内存可靠性不如磁盘。所以性能方面比MapReduce要好。
DAG计算模型在迭代计算上,比MapReduce的效率更高。
2、Spark中具有DAG有向无环图,DAG有向无环图在此过程中减少了Shuffle以及落地磁盘的次数。
Spark 计算比 MapReduce 快的根本原因在于 DAG 计算模型。
一般而言,DAG 相比MapReduce 在大多数情况下可以减少 Shuffle 次数。Spark 的 DAGScheduler 相当于一个改进版的 MapReduce,如果计算不涉及与其他节点进行数据交换,Spark 可以在内存中一次性完成这些操作,也就是中间结果无须落盘,减少了磁盘 IO 的操作。
但是,如果计算过程中涉及数据交换,Spark 会把 Shuffle 的数据写磁盘的。
有一个误区,Spark 是基于内存的计算,所以快,这不是主要原因,要对数据做计算,必然得加载到内存。Hadoop 也是如此,只不过 Spark 支持将需要反复用到的数据给 Cache 到内存中,减少数据加载耗时,所以 Spark 跑机器学习算法比较在行(需要对数据进行反复迭代)。Spark 基于磁盘的计算也比 Hadoop 快。
刚刚我们提到 Spark 的 DAGScheduler 是个改进版的 MapReduce,所以 Spark天生适合做批处理的任务。Hadoop 的 MapReduce 虽然不如 Spark 性能好,但是 HDFS 仍然是业界的大数据存储标准。
3、Spark是粗粒度资源申请,也就是当提交Spark Application的时候,Application会将所有的资源申请完毕,如果申请不到资源就等待。
如果申请到资源才执行Application,Task在执行的时候就不需要自己去申请资源,Task执行快,当最后一个Task执行完之后,Task才会被释放。
执行速度快; 缺点是:不能使集群得到充分的利用。
MapReduce是细粒度资源申请,当提交Application的时候,Task执行时,自己申请资源,自己释放资源,Task执行完毕之后,资源立即会被释放,Task执行的慢,Application执行的相对比较慢。
集群资源得到充分利用,缺点是:Application执行的相对比较慢。
3 问题扩展
Spark的Shuffle 与 MapReduce的Shuffle区别?
4 结合项目中使用
Apache Spark,一个内存数据处理的框架,是一个顶级Apache项目,后续逐渐取代MapReduce。
MapReduce是非常有用的,但现在Spark开始从它手中接过缰绳,成为新的Hadoop工作负载的主要处理框架。
该技术比MapReduce的速度更快、更容易编程,Spark已经囊括大量的用户和代码贡献者。 这意味着它非常适合用于下一代大数据的应用程序,它们有更低的延迟查询,实时处理或在相同的数据上的迭代计算的能力(即,机器学习)。
Spark 从技术上讲是一个独立的项目,但它总是设计用来与Hadoop分布式文件系统一起工作 。 它可以直接在HDFS上运行, 以及通过YARN,它可以和同一群集上的MapReduce作业一起运行。 事实上,Hadoop的先驱Cloudera公司现在为Spark客户提供企业级支持。
1 问题分析
本题旨在考察面试者是否了解Spark以及Spark的使用场景。
2 核心答案讲解
是其它组件的基础,Spark的内核,主要包含:有向循环图、RDD、Lingage、Cache、Broadcast等,并封装了底层通讯框架,是Spark的基础。
(类似于storm)可以对实时数据流进行高通量、容错处理的流式处理系统,可以对多种数据源(如Kafka、Flume、Twitter、Zero和TCP 套接字)进行类似于Hadoop中的Map、Reduce和Join等复杂操作,将流式计算分解成一系列短小的批处理作业。
Shark是Spark SQL的前身,Spark SQL的一个重要特点是其能够统一处理关系表和 RDD(弹式分布数据集),使得开发人员可以轻松地使用SQL命令进行外部查询,同时进行更复杂的数据分析。
是一个在海量数据上运行交互式 SQL 查询的,大规模并行查询引擎,它允许用户通过权衡数据精度来提升查询响应时间,其数据的精度被控制在允许的误差范围内。
5)是Spark生态圈的一部分专注于机器学习,让机器学习的门槛更低,让一些可能并不了解机器学习的用户也能方便地使用MLBase。
分为四部分:MLlib、MLI、ML Optimizer和MLRuntime。
6),Spark中用于图和图并行计算。
3 问题扩展
Spark的有几种部署模式以及每种模式特点?
4 结合项目中使用
1 问题分析
Spark的部署模式,以及特点、场景是大多数面试的必问点。
2 核心答案讲解
1)本地模式Spark不一定非要跑在Hadoop集群,也可以在本地起多个线程的方式来指定。
将Spark应用以多线程的方式直接运行在本地,一般都是为了方便调试。
本地模式分三类
· local:只启动一个Executor
· local[k]:启动k个Executor
· local[*]:启动跟CPU数目相同的Executor
2)Standalone模式分布式部署集群, 自带完整的服务,资源管理和任务监控是Spark自己监控,这个模式也是其他模式的基础。
3)Spark On YARN模式分布式部署集群,资源和任务监控交给YARN管理,但是目前仅支持粗粒度资源分配方式,包含Cluster和Client运行模式。
Cluster适合生产,Driver运行在集群子节点,具有容错功能,Client适合调试,Dirver运行在客户端。
4)Spark On Mesos模式
官方推荐这种模式(当然,原因之一是血缘关系)。
正是由于Spark开发之初就考虑到支持Mesos,因此,目前而言,Spark运行在Mesos上会比运行在YARN上更加灵活,更加自然。
用户可选择两种调度模式之一运行自己的应用程序:
每个应用程序的运行环境,由一个Dirver和若干个Executor组成,其中,每个Executor占用若干资源,内部可运行多个Task(对应多少个“slot”)。
应用程序的各个任务正式运行之前,需要将运行环境中的资源全部申请好,且运行过程中要一直占用这些资源。如果不用,最后程序运行结束后,回收这些资源。
鉴于粗粒度模式会造成大量资源浪费,Spark On Mesos还提供了另外一种调度模式:细粒度模式,这种模式类似于现在的云计算,思想是按需分配。
3 问题扩展
Spark On YARN的部署模式流程
1 问题分析
Spark,不同于MapReduce的是:Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等需要迭代的MapReduce算法。
2 核心答案讲解
可以增大Driver的内存参数:spark.driver.memory (default 1g) , 这个参数用来设置Driver的内存。
在Spark程序中,SparkContext,DAGScheduler都是运行在Driver端的。对应RDD的Stage切分也是在Driver端运行,如果用户自己写的程序有过多的步骤,切分出过多的Stage,这部分信息消耗的是Driver的内存,这时候就需要调大Driver的内存。
这种溢出的原因是在单个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的过程。
数据不平衡除了有可能导致内存溢出外,还有可能导致性能的问题,解决方法和上面说的类似,就是调用repartition方法重新分区,这里不再赘述。
Shuffle内存溢出的情况可以说:大多是Shuffle后单个文件过大导致的。
在Spark中,Join,ReduceByKey 这一类型的过程,都会有Shuffle的过程,在Shuffle的使用,需要传入一个Partitioner,大部分Spark中的Shuffle操作,默认的Partitioner都是HashPatitioner,默认值是父RDD中最大的分区数,这个参数通过spark.default.parallelism控制(在spark-sql中用spark.sql.shuffle.partitions) , spark.default.parallelism参数只对HashPartitioner有效。
即:如果是别的Partitioner或者自己实现的Partitioner,就不能使用spark.default.parallelism这个参数来控制Shuffle的并发量了。
如果是别的Partitioner导致的Shuffle内存溢出,就需要从Partitioner的代码增加Partitions的数量。
在Standalone的模式下如果配置了--total-executor-cores 和 --executor-memory 这两个参数,但是没有配置--executor-cores这个参数的话,就有可能导致此现象。
每个Executor的memory是一样的,但是cores的数量不同,那么在cores数量多的Executor中,由于能够同时执行多个Task,就容易导致内存溢出的情况。
这种情况的解决方法就是同时配置--executor-cores或者spark.executor.cores参数,确保Executor资源分配均匀。
rdd.cache()和rdd.persist(Storage.MEMORY_ONLY)是等价的,在内存不足的时候rdd.cache()的数据会丢失,再次使用的时候会重算,而rdd.persist(StorageLevel.MEMORY_AND_DISK_SER)在内存不足的时候会存储在磁盘,避免重算,只是消耗点IO时间。
3 问题扩展
4 结合项目中使用
一个原则,你能使用的资源有多大,就尽量去调节到最大的大小(Executor的数量,几十个到上百个不等;Executor内存;Executor CPU Core)
到此这篇spark面试题及答案100道(spark面试题shuffle)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/56130.html