Apache Spark

sparkCore源码解析之Job

谁都会走 提交于 2019-12-29 17:39:11
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 1. 概念 站在不同的角度看job transaction: Job是由一组RDD上转换和动作组成。 stage: Job是由ResultStage和多个ShuffleMapState组成 init:由action操作触发提交执行的一个函数 action操作会触发调用sc.runJob方法, Job是一组rdd的转换以及最后动作的操作集合,它是Spark里面计算最大最虚的概念,甚至在spark的任务页面中都无法看到job这个单位。 但是不管怎么样,在spark用户的角度,job是我们计算目标的单位,每次在一个rdd上做一个动作操作时,都会触发一个job,完成计算并返回我们想要的数据。 Job是由一组RDD上转换和动作组成 ,这组RDD之间的转换关系表现为一个有向无环图(DAG),每个RDD的生成依赖于前面1个或多个RDD。 在Spark中,两个RDD之间的依赖关系是Spark的核心。站在RDD的角度,两者依赖表现为点对点依赖, 但是在Spark中,RDD存在分区(partition)的概念,两个RDD之间的转换会被细化为两个RDD分区之间的转换。 Stage的划分是对一个Job里面一系列RDD转换和动作进行划分。 首先job是因动作而产生,因此每个job肯定都有一个ResultStage,否则job就不会启动。

sparkCore shuffle解析

橙三吉。 提交于 2019-12-29 17:38:49
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 转载:时延军. http://shiyanjun.cn Spark在Map阶段调度运行的ShuffleMapTask,最后会生成.data和.index文件,可以通过我的这篇文章 Spark Shuffle过程分析:Map阶段处理流程 了解具体流程和详情。同时,在Executor上运行一个ShuffleMapTask,返回了一个MapStatus对象,下面是ShuffleMapTask执行后返回结果的相关代码片段: var writer: ShuffleWriter[Any, Any] = null try { val manager = SparkEnv.get.shuffleManager writer = manager.getWriter[Any, Any](dep.shuffleHandle, partitionId, context) writer.write(rdd.iterator(partition, context).asInstanceOf[Iterator[_ <: Product2[Any, Any]]]) writer.stop(success = true).get } catch { case e: Exception => try { if (writer != null) {

sparkCore源码解析之shuffle

大城市里の小女人 提交于 2019-12-29 17:38:39
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> Shuffle Map的过程,即Shuffle Stage的ShuffleTask按照一定的规则将数据写到相应的文件中,并把写的文件"位置信息" 以MapOutput返回给DAGScheduler ,MapOutput将它更新到特定位置就完成了整个Shuffle Map过程. 在Spark中,Shuffle reduce过程抽象化为ShuffledRDD,即这个RDD的compute方法计算每一个分片即每一个reduce的数据是通过拉取ShuffleMap输出的文件并返回Iterator来实现的 1. 对比MapReduce 1.1. 宏观比较 两者差别不大,度分为map和reduce两个阶段 。 从 high-level 的角度来看,两者并没有大的差别。 都是将 mapper(Spark 里是 ShuffleMapTask)的输出进行 partition,不同的 partition 送到不同的 reducer(Spark 里 reducer 可能是下一个 stage 里的 ShuffleMapTask,也可能是 ResultTask)。Reducer 以内存作缓冲区,边 shuffle 边 aggregate 数据,等到数据 aggregate 好以后进行 reduce() (Spark

sparkCore源码解析之partition

江枫思渺然 提交于 2019-12-29 17:38:25
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 1. 概念 表示并行计算的一个计算单元 RDD 内部的数据集合在逻辑上和物理上被划分成多个小子集合,这样的每一个子集合我们将其称为分区,分区的个数会决定并行计算的粒度,而每一个分区数值的计算都是在一个单独的任务中进行,因此并行任务的个数,也是由 RDD(实际上是一个阶段的末 RDD,调度章节会介绍)分区的个数决定的 2. 获取分区 RDD的分区数量可通过rdd.getPartitions获取。 getPartitions方法是在RDD类中定义的,由不同的子类进行具体的实现 2.1. 接口 获取分区的定义 在RDD类中定义了getPartition方法,返回一个Partition列表,Partition对象只含有一个编码index字段,不同RDD的partition会继承Partition类,例如JdbcPartition、KafkaRDDPartition,HadoopPartition等。 class RDD{ // 获取分区定义 def getPartitions:Array[Partition] } // Partition类定义 trait Partition { def index:Int } 2.2. 实现 transformation类型的RDD分区数量和父RDD的保持一致

sparkCore源码解析之block

主宰稳场 提交于 2019-12-29 17:27:24
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 1. 标记 Apache Spark中,对Block的查询、存储管理,是通过唯一的Block ID来进行区分的。 同一个Spark Application,以及多个运行的Application之间,对应的Block都具有唯一的ID 1.1. 种类 需要在worker和driver间共享数据时,就需要对这个数据进行唯一的标识,常用的需要传输的block信息有以下几类 RDDBlockId、ShuffleBlockId、ShuffleDataBlockId、ShuffleIndexBlockId、BroadcastBlockId、TaskResultBlockId、TempLocalBlockId、TempShuffleBlockId 1.2. 生成规则 RDDBlockId : "rdd_" + rddId + "_" + splitIndex ShuffleBlockId : "shuffle_" + shuffleId + "_" + mapId + "_" + reduceId ShuffleDataBlockId:"shuffle_" + shuffleId + "_" + mapId + "_" + reduceId + ".data" ShuffleIndexBlockId:"shuffle_" +

map join 和 reduce join

倖福魔咒の 提交于 2019-12-29 17:27:15
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 在大数据处理场景中,多表Join是非常常见的一类运算。为了便于求解,通常会将多表join问题转为多个两表连接问题。两表Join的实现算法非常多,一般我们会根据两表的数据特点选取不同的join算法,其中,最常用的两个算法是map-side join和reduce-side join。本文将介绍如何在apache spark中实现这两种算法。 Map-side Join Map-side Join使用场景是一个大表和一个小表的连接操作,其中,“小表”是指文件足够小,可以加载到内存中。该算法可以将join算子执行在Map端,无需经历shuffle和reduce等阶段,因此效率非常高。 在Hadoop MapReduce中, map-side join是借助DistributedCache实现的。DistributedCache可以帮我们将小文件分发到各个节点的Task工作目录下,这样,我们只需在程序中将文件加载到内存中(比如保存到Map数据结构中),然后借助Mapper的迭代机制,遍历另一个大表中的每一条记录,并查找是否在小表中,如果在则输出,否则跳过。 Reduce-side Join 当两个文件/目录中的数据非常大,难以将某一个存放到内存中时,Reduce-side Join是一种解决思路

Spark stage介绍

烈酒焚心 提交于 2019-12-29 17:18:39
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 窄依赖和宽依赖 窄依赖: 指父RDD的每一个分区最多被一个子RDD的分区所用,表现为一个父RDD的分区对应于一个子RDD的分区,和两个父RDD的分区对应于一个子RDD 的分区。图中,map/filter和union属于第一类,对输入进行协同划分(co-partitioned)的join属于第二类。 宽依赖: 指子RDD的分区依赖于父RDD的所有分区,这是因为shuffle类操作,如图中的groupByKey和未经协同划分的join。 Stage: 一个Job会被拆分为多组Task,每组任务被称为一个Stage就像Map Stage, Reduce Stage。Stage的划分在RDD的论文中有详细的介绍,简单的说是以shuffle和result这两种类型来划分。在Spark中有两类task,一类是shuffleMapTask,一类是resultTask,第一类task的输出是shuffle所需数据,第二类task的输出是result,stage的划分也以此为依据,shuffle之前的所有变换是一个stage,shuffle之后的操作是另一个stage。比如 rdd.parallize(1 to 10).foreach(println) 这个操作没有shuffle,直接就输出了

Spark的另一个核心的奥秘:任务

淺唱寂寞╮ 提交于 2019-12-29 17:09:40
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 任务(Task)是Spark的最小执行单元,Spark任务是通过Task来执行的。Spark的任务体系是最神秘也是最容易学习的核心模块,任务执行机制点透了那么Spark也就了解的更深入了。Task是任务体系的一个抽象类,有两个子类:ResultTask和ShuffleMapTask,这三个类构成了任务系统的核心。 ResultTask好理解,就是直接执行Task中RDD某个分区的数据操作,还记得之前的RDD的结构吗,里面有一个compute函数,任务就是执行compute函数。 ShuffleMapTask也是执行Task中RDD某个分区的数据操作,所不同的是输出结果的存储方式不一样。ShuffleMapTask会把数据操作的结果保存到类似BlockManager的全局存储中,ShuffleMapTask的结果可供下一个Task作为输入数据。为什么分两种呢?换个说法就很清楚了,ResultTask对应窄依赖的RDD,ShuffleMapTask对应宽依赖的RDD操作(如全连接操作)。ShuffleMapTask需要对数据的读写进行特殊的处理,要用BlockManager来输出数据集的;同样,ShuffleMapTask的子RDD的读取数据集也是从BlockManager来的。

Spark On Yarn 中出现的问题记录

无人久伴 提交于 2019-12-29 16:47:22
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 1:运行候一直retry master:8032的问题 分析: 可能是因为yarn没有启动。 解决: 检查是否启动了服务. 用jps命令查看相关信息[是否存在ResourceManager] 2: mory used; 2.2 GB of 2.1 GB virtual memory used. Killing container. 分析: 可能是内存不够的问题,因为自己是使用的虚拟机内存只分配了1G,后来百度了下并不是物理内存的问题,yarn执行会检查虚拟内存,如果虚拟内存不够就会报此错误。 解决: 在{hadoopdir}/etc/Hadoop/yarn-site.xml文件中,修改检查虚拟内存的属性为false,如下: <property> <name>yarn.nodemanager.vmem-check-enabled</name> <value>false</value> </property> 3:Neither spark.yarn.jars nor spark.yarn.archive is set, falling back to uploading libraries under SPARK_HOME. 不影响运行,但每次执行yarn都会把spark目录下的jars的包传到hdfs上

BlockManager -- Spark自己的分布式存储系统

限于喜欢 提交于 2019-12-29 16:30:13
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 概述 BlockManager是spark自己的存储系统,RDD-Cache、 Shuffle-output、broadcast 等的实现都是基于BlockManager来实现的,BlockManager也是分布式结构,在driver和所有executor上都会有blockmanager节点,每个节点上存储的block信息都会汇报给driver端的blockManagerMaster作统一管理,BlockManager对外提供get和set数据接口,可将数据存储在memory, disk, off-heap。 blockManager的创建与注册 blockManagerMaster和blockManager都是在构造SparkEnv的时候创建的,Driver端是创建SparkContext的时候创建SparkEnv,Executor端的SparkEnv是在其守护进程CoarseGrainedExecutorBackend创建的时候创建的,下面看blockManager是怎么在sparkEnv中创建的: // get&put 远程block的时候就是通过blockTransferService 完成的 val blockTransferService = new