通过上面一系列文章,我们知道在集群启动时,在Standalone模式下,Worker会向Master注册,使得Master可以感知进而管理整个集群;Master通过借助ZK,可以简单的实现HA;而应用方通过SparkContext这个与集群的交互接口,在创建SparkContext时就完成了Application的注册,Master为其分配Executor;在应用方创建了RDD并且在这个RDD上进行了很多的Transformation后,触发action,通过DAGScheduler将DAG划分为不同的Stage后,将Stage转换为TaskSet交给TaskSchedulerImpl;TaskSchedulerImpl通过SparkDeploySchedulerBackend的reviveOffers,最终向ExecutorBackend发送LaunchTask的消息;ExecutorBackend接收到消息后,启动Task,开始在集群中启动计算。

接下来,会介绍一些更详细的细节实现。

Shuffle,无疑是性能调优的一个重点,本文将从源码实现的角度,深入解析Spark Shuffle的实现细节。

每个Stage的上边界,要不是需要从外部存储读取数据,要么需要读取上一个Stage的输出;而下边界,要么是需要写入本地文件系统,以供child Stage读取,要么是ResultTask,需要输出结果了。

首先从org.apache.spark.rdd.ShuffledRDD开始, 因为ShuffledRDD是一个Stage的开始,它需要获取上一个Stage的输出结果,然后进行接下来的运算。那么这个数据获取是如何实现的?顺着ShuffledRDD的实现,我们可以理清这条线。首先可以看一下compute是如何实现的。

  override def compute(split: Partition, context: TaskContext): Iterator[(K, C)] = {
val dep = dependencies.head.asInstanceOf[ShuffleDependency[K, V, C]]
SparkEnv.get.shuffleManager.getReader(dep.shuffleHandle, split.index, split.index + 1, context)
.read()
.asInstanceOf[Iterator[(K, C)]]
}

它需要从ShuffleManager获取shuffleReader,然后读取数据进行计算。看一下shuffleManager:

 // Let the user specify short names for shuffle managers
val shortShuffleMgrNames = Map(
"hash" -> "org.apache.spark.shuffle.hash.HashShuffleManager",
"sort" -> "org.apache.spark.shuffle.sort.SortShuffleManager")
val shuffleMgrName = conf.get("spark.shuffle.manager", "hash")
val shuffleMgrClass = shortShuffleMgrNames.getOrElse(shuffleMgrName.toLowerCase, shuffleMgrName)
val shuffleManager = instantiateClass[ShuffleManager](shuffleMgrClass)

ShuffleManager分为hash和sort,hash是默认的,即Shuffle时不排序。熟悉MapReduce的同学都知道,MapReduce是无论如何都要排序的,即到Reduce端的都是已经排序好的,当然这么做也是为了可以处理海量的数据。在Spark1.1之前,只支持hash based的Shuffle,sort based Shuffle是1.1新加入的实验功能。

hash顾名思义,在Reduce时的数据需要求有序,因此可以在Reduce获得了数据后,立即进行处理;而不需要等待所有的数据都得到后再处理。这个接下来会通过源码进行解释。而sort,意味着排序,实际上对于sortByKey这种转换可能sort是更有意义的。

ShuffledRDD是通过org.apache.spark.shuffle.hash.HashShuffleReader获取上一个Stage的结果。而HashShuffleReader通过org.apache.spark.shuffle.hash.BlockStoreShuffleFetcher$#fetch来获取结果。而fetch通过调用org.apache.spark.storage.BlockManager#getMultiple来转发请求:

  def getMultiple(
blocksByAddress: Seq[(BlockManagerId, Seq[(BlockId, Long)])],
serializer: Serializer,
readMetrics: ShuffleReadMetrics): BlockFetcherIterator = {
val iter = new BlockFetcherIterator.BasicBlockFetcherIterator(this, blocksByAddress, serializer,
readMetrics)
iter.initialize()
iter
}

而最终的实现在org.apache.spark.storage.BlockFetcherIterator.BasicBlockFetcherIterator#initialize中,

  override def initialize() {
// Split local and remote blocks.
// 获得需要远程请求的数据列表,并且将已经在本地的数据的blockid放在localBlocksToFetch中,
// 并且在org.apache.spark.storage.BlockFetcherIterator.BasicBlockFetcherIterator.getLocalBlocks进行本地读取
val remoteRequests = splitLocalRemoteBlocks()
// Add the remote requests into our queue in a random order
fetchRequests ++= Utils.randomize(remoteRequests) // Send out initial requests for blocks, up to our maxBytesInFlight
while (!fetchRequests.isEmpty && //保证占用内存不超过设定的值spark.reducer.maxMbInFlight,默认值是48M
(bytesInFlight == 0 || bytesInFlight + fetchRequests.front.size <= maxBytesInFlight)) {
sendRequest(fetchRequests.dequeue())
} val numFetches = remoteRequests.size - fetchRequests.size
logInfo("Started " + numFetches + " remote fetches in" + Utils.getUsedTimeMs(startTime)) // Get Local Blocks
startTime = System.currentTimeMillis
getLocalBlocks() // 从本地获取
logDebug("Got local blocks in " + Utils.getUsedTimeMs(startTime) + " ms")
}

具体获取如何获取的策略都在org.apache.spark.storage.BlockFetcherIterator.BasicBlockFetcherIterator#splitLocalRemoteBlocks中。这个会在下一篇博文中详解。

Spark技术内幕: Shuffle详解(一)的更多相关文章

  1. Spark技术内幕: Shuffle详解(三)

    前两篇文章写了Shuffle Read的一些实现细节.但是要想彻底理清楚这里边的实现逻辑,还是需要更多篇幅的:本篇开始,将按照Job的执行顺序,来讲解Shuffle.即,结果数据(ShuffleMap ...

  2. Spark技术内幕: Shuffle详解(二)

    本文主要关注ShuffledRDD的Shuffle Read是如何从其他的node上读取数据的. 上文讲到了获取如何获取的策略都在org.apache.spark.storage.BlockFetch ...

  3. [Spark内核] 第36课:TaskScheduler内幕天机解密:Spark shell案例运行日志详解、TaskScheduler和SchedulerBackend、FIFO与FAIR、Task运行时本地性算法详解等

    本課主題 通过 Spark-shell 窥探程序运行时的状况 TaskScheduler 与 SchedulerBackend 之间的关系 FIFO 与 FAIR 两种调度模式彻底解密 Task 数据 ...

  4. Spark技术内幕:Stage划分及提交源码分析

    http://blog.csdn.net/anzhsoft/article/details/39859463 当触发一个RDD的action后,以count为例,调用关系如下: org.apache. ...

  5. Spark技术内幕: Task向Executor提交的源码解析

    在上文<Spark技术内幕:Stage划分及提交源码分析>中,我们分析了Stage的生成和提交.但是Stage的提交,只是DAGScheduler完成了对DAG的划分,生成了一个计算拓扑, ...

  6. Spark技术内幕: Task向Executor提交的源代码解析

    在上文<Spark技术内幕:Stage划分及提交源代码分析>中,我们分析了Stage的生成和提交.可是Stage的提交,仅仅是DAGScheduler完毕了对DAG的划分,生成了一个计算拓 ...

  7. 前端技术之_CSS详解第一天

    前端技术之_CSS详解第一天 一html部分 略.... 二.列表 列表有3种 2.1 无序列表 无序列表,用来表示一个列表的语义,并且每个项目和每个项目之间,是不分先后的. ul就是英语unorde ...

  8. 前端技术之_CSS详解第二天

    前端技术之_CSS详解第二天 1.css基础选择器 html负责结构,css负责样式,js负责行为. css写在head标签里面,容器style标签. 先写选择器,然后写大括号,大括号里面是样式. & ...

  9. Spark技术内幕:Master的故障恢复

    Spark技术内幕:Master基于ZooKeeper的High Availability(HA)源码实现  详细阐述了使用ZK实现的Master的HA,那么Master是如何快速故障恢复的呢? 处于 ...

随机推荐

  1. [POI2009]KAM-Pebbles

    题目描述 Johny and Margaret are playing "pebbles". Initially there is a certain number of pebb ...

  2. codeforces round #419 E. Karen and Supermarket

    On the way home, Karen decided to stop by the supermarket to buy some groceries. She needs to buy a ...

  3. [Codeforces]813F Bipartite Checking

    往期题目补档.既然被选为了经典题就拿来写一写. Description 给定一张含有n个点的无向图,一开始图中没有任何边.依次给出q次操作,每次操作给出两个点“x y”,若x和y之间没有边相连,则连上 ...

  4. Xtrabackup2.4.8备份、还原、恢复Mysql5.7.19实操

    环境:CentOS 6.7  + Mysql 5.7.19 + Xtraback 2.4.8 innobackupex常用参数: --user=USER 指定备份用户,不指定的话为当前系统用户 --p ...

  5. USB_ESD处理

    今天收到客户反馈说碰到USB后机器会死机,之前一直没有关注ESD问题. 现在整理之前用过的成熟的ESD电路: 电感为 PZ3216D101-3R0TF,1206封装. 用ESD枪测试OK, 用打火机持 ...

  6. Vue2学习结合bootstrapTable遇到的问题

    Vue2学习 项目中在使用bootstrapTable的时候,在table里面会有操作结合vue使用过程中点击相应的操作不会起作用 解决办法 1.把事件绑定到父元素上即可,但要判断什么样的需要点击,用 ...

  7. Spring MVC运行流程

    一.配置阶段 ①web.xml ②DispatcherServlet    //Spring MVC总入口 ③配置初始化参数   //classpath:application.xml,用于配置无数个 ...

  8. Spring中@Autowired与@Resource的区别

    1.@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter方法上. 2.@Autowired默认按类型装配(这个注解是属业spring的),默认情况下必 ...

  9. c# 操作数据库

    查询 string strConnection = "Data Source=(local);Initial Catalog=zpractice;Integrated Security=SS ...

  10. 【阿里聚安全·安全周刊】Google“手枪”替换 | 伊朗中央银行禁止加密货币

    本周七个关键词:Google"手枪"替换丨IOS 漏洞影响工业交换机丨伊朗中央银行禁止加密货币丨黑客针对医疗保健丨付费DDoS攻击丨数据获利的8种方式丨MySQL 8.0 正式版 ...