Spark是一个极速的大数据处置引擎,在实践的消费环境中,运行十分宽泛。目前,Spark依然是大数据开发十分关键的一个工具,所以在面试的环节中,Spark也会是被重点调查的对象。关于初学者而言,面对单一的Spark相关概念,一时会难以厘清眉目,关于经常使用Spark开发的同窗而言,有时刻也会对这些概念感到含糊。本文关键梳理了几个关于Spark的比拟关键的几个概念,在面试的环节中假设被问到Spark相关的疑问,详细可以从以下几个方面开展即可,宿愿对你有所协助。本文关键包括以下内容:
组成
Spark栈包括SQL和DataFrames,MLlib机器学习,GraphX和SparkStreaming。用户可以在同一个运行程序中无缝组合经常使用这些库。
架构
Spark运转架构包括集群资源治理器(Cluster Manager)、运转作业义务的上班节点(WorkerNode)、每个运行的义务控制节点(Driver)和每个上班节点上担任详细义务的执后退程(Executor)。其中,集群资源治理器可以是Spark自带的资源治理器,也可以是YARN或Mesos等资源治理框架。
运转流程
MapReduce VS Spark
与Spark相比,MapReduce具备以下缺陷:
与MapReduce相比,Spark具备以下好处:详细包括两个方面
驱动程序(Driver)和Executor
运转main函数的驱动程序进程位于集群中的一个节点上,担任三件事:
驱动程序进程是相对必要的——它是 Spark 运行程序的**,并在运行程序的生命周期内保养一切相关消息。
Executor担任实践执行驱动程序调配给他们的义务。这象征着每个Executor只担任两件事:
分区
为了让每个 executor 并行执行上班,Spark 将数据合成成称为partitions的块。分区是位于集群中一台物理机器上的行的汇合。Dataframe 的分区示意数据在执行时期如何在机器集群中物理散布。
假设你有一个分区,即使你有数千个Executor,Spark 的并行度也只要一个。假设你有很多分区但只要一个执行器,Spark依然只要一个并行度,由于只要一个计算资源。
执行形式:Client VS Cluster VS Local
执行形式能够在运转运行程序时确定Driver和Executor的物理位置。
有三种形式可供选用:
集群形式 或许是运转 Spark运行程序最经常出现的方式。在集群形式下,用户将预编译的代码提交给集群治理器。除了启动Executor之外,集群治理器会在集群内的上班节点(work)上启动驱动程序(Driver)进程。这象征着集群治理器担任治理与Spark 运行程序相关的一切进程。
客户端形式 与集群形式简直相反,只是 Spark 驱动程序保管在提交运行程序的客户端节点上。这象征着客户端机器担任保养 Spark driver进程,集群治理器保养 executor 进程。通常将这个节点称之为网关节点。
本地形式可以被以为是在你的计算机上运转一个程序,spark 会在同一个 JVM 中运转驱动程序和执行程序。
RDD VS>
如上图,首先Driver将序列化对象宰割成小的数据库,而后将这些数据块存储在Driver节点的BlockManager上。当ececutor中执行详细的task时,每个executor首先尝试从自己所在节点的BlockManager提取数据,假设之前曾经提取的该广播变量的值,就间接经常使用它。假设没有找到,则会向远程的Driver或许其余的Executor中提取广播变量的值,一旦失掉该值,就将其存储在自己节点的BlockManager中。这种机制可以防止Driver端向多个executor发送数据而形成的性能瓶颈。
累加器
累加器(Accumulator)是Spark提供的另外一个共享变量,与广播变量不同,累加器是可以被修正的,是可变的。每个transformation会将修正的累加器值传输到Driver节点,累加器可以成功一个累加的性能,相似于一个计数器。Spark自身支持数字类型的累加器,用户也可以自定义累加器的类型。
宽依赖和窄依赖
RDD中不同的操作会使得不同RDD中的分区产不同的依赖,关键有两种依赖:宽依赖和窄依赖。宽依赖是指一个父RDD的一个分区对应一个子RDD的多个分区,窄依赖是指一个父RDD的分区对应与一个子RDD的分区,或许多个父RDD的分区对应一个子RDD分区。
窄依赖会被划分到同一个stage中,这样可以以管道的方式迭代执行。宽依赖所依赖的分区普通有多个,所以须要跨节点传输数据。冷静灾方面看,两种依赖的计算结果复原的方式是不同的,窄依赖只要要复原父RDD失落的分区即可,而宽依赖则须要思考复原一切父RDD失落的分区。
DAGScheduler会将Job的RDD划分到不同的stage中,并构建一个stage的依赖相关,即DAG。这样划分的目的是既可以保证没有依赖相关的stage可以并行执行,又可以保证存在依赖相关的stage顺序执行。stage关键分为两种类型,一种是ShuffleMapStage,另一种是ResultStage。其中ShuffleMapStage是属于抢先的stage,而ResulStage属于最下游的stage,这象征着抢先的stage先执行,最后执行ResultStage。
耐久化
方式
在Spark中,RDD驳回惰性求值的机制,每次遇到action操作,都会从头开局执行计算。每次调用action操作,都会触发一次性从头开局的计算。关于须要被重复经常使用的RDD,spark支持对其启动耐久化,经过调用persist()或许cache()方法即可成功RDD的持方案。经过耐久化机制可以防止重复计算带来的开支。值得留意的是,当调用耐久化的方法时,只是对该RDD标志为了耐久化,须要等到第一次性执行action操作之后,才会把计算结果启动耐久化。耐久化后的RDD将会被保管在计算节点的内存中被前面的执行操作重复经常使用。
Spark提供的两个耐久化方法的关键区别是:cache()方法自动经常使用的是内存级别,其底层调用的是persist()方法。
耐久化级别的选用
Spark提供的耐久化存储级别是在内存经常使用与CPU效率之间做掂量,通常介绍上方的选用方式:
tips:在一些shuffle算子中,比如reduceByKey,即使没有显性调用persist方法,Spark也会智能将两边结果启动耐久化,这样做的目的是防止在shuffle时期出现缺点而形成从新计算整个输入。即使如此,还是介绍对须要被重复经常使用的RDD启动耐久化处置。
coalesce VS repartition
repartition算法对数据启动了shuffle操作,并创立了大小相等的数据分区。coalesce操作兼并现有分区以防止shuffle,除此之外coalesce操作仅能用于缩小分区,不能用于参与分区。
值得留意的是:经常使用coalesce在缩小分区时,并没有对一切数据启动了移动,仅仅是在原来分区的基础之上启动了兼并而已,所以效率较高,然而或许会惹起数据歪斜。
综合案例
一种数仓技术架构
SparkStreaming实时同步
SparkStreaming消费kafka埋点数据
将解析的数据同时写入HDFS上的某个暂时目录下及Hive表对应的分区目录下
由于是实时数据抽取,所以会生成少量的小文件,小文件的生成取决于SparkStreaming的BatchInterval,比如一分钟一个batch,那么一分钟就会生成一个小文件
基于SparkSQL的批处置
SparkStreaming数据输入是At LeastOnce,或许会存在数据重复。在ODS层到DWD层启动明细数据处置时,须要对数据经常使用row_number去重。
数据量大时,须要对数据启动重分区,并且为DataSet分区级别建设衔接,驳回批量提交的方式。
spark.sql.shuffle.partitions的自动值为200,会造成以下疑问
经常使用 DISTRIBUTE BY cast( rand * N as int) 这里的N是指详细最后落地生成多少个文件数。
手动保养offset至HBase
当作业出现缺点或重启时,要保证从的消费位点去处置数据,单纯的依托SparkStreaming自身的机制是不太理想,消费环境中通常借助手动治理来保养kafka的offset。
流运行监控诉警