热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Spark原理】Spark内部原理学习笔记

1总体框架结构图Spark应用程序架构由上图我们可以看到Spark应用程序架构主要由DriverProgram和Executor构成,Driver负责运行main()和创建Spar
1 总体框架结构图

《【Spark原理】Spark内部原理学习笔记》 Spark应用程序架构

由上图我们可以看到Spark应用程序架构主要由Driver Program和Executor构成,Driver负责运行main()和创建SparkContext,Executor主要负责执行Task任务。

2 各大重要组件和概念

2.1 重要概念

概念功能模型备注
Application用户定义的Spark应用程序,用户提交后,Spark会为应用分配资源,调度和执行相关任务.
RDD GraphSpark会分析Spark应用,将程序中所涉及的RDD按照一定的依赖关系构建RDD Graph,也就是根据算子来构建有向无环图,每个RDD Graph都会转化成一个Job
Job– 一个App中可以包含多个Job,每个Job都是由一个RDD Graph转化而来的
– 由Action算子触发
.
Stage– 每个Job会根据RDD之间的宽依赖(Shuffle Dependency)来划分成多个Stage,每一个Stage中包含一组Task(也就是TaskSet)
– 每个Stage中的Task类型都是相同的
.
Task– 一个分区对应一个Task
– Task执行RDD中对应的算子,Task被封装TaskRunner后放入Executor的线程中来执行,并由TaskRunner来进行调度
– Task类型有ShuffleMapTask和ResultTask
.
Worker可以运行App代码的节点,如Yarn中NodeManager.
DAGScheduler用来构建基于Stage的有向无环图,划分的依据是根据RDD之间的宽依赖.
TaskScheduler– 将TaskSet提交给Executor去运行
– 维护TaskSet的运行状态标签,负责Task的失效重执行
.

2.2 相关组件

组件功能模型备注
Driver– 运行Application的main函数并创建SparkContext
– SparkContext的作用就是与Cluster Manager通讯,进行资源申请、任务的调度等。
.
Executor– 某个App运行在Worker上的一个进程,用于执行App的Task
– 每个App都有独立的Executor,Executor上运行的Task取决于分配的core数
.
Cluster Manager资源调度服务,用于资源的分配和调度,有standalone、mesos和yarn三种模式.
3 应用的提交执行流程

3.1 运行模式

1)Spark应用的运行模式有以下几种:

  • local[n]:本地模式
  • standalone:使用spark内部的资源管理器,master-slaves架构
  • mesos : Apache下的一个资源管理框架
  • yarn : Hadoop下的一个资源管理框架

2)根据Driver的运行位置来划分有以下两种运行模式:

  • Cluster:Driver和Executor运行在集群中的Worker上
  • Client:Driver运行在客户端上,Executor运行在Worker上

3)命令行

  • spark-shell:bin/spark-shell –master yarn –deploy-mode client(yarn的client模式)
  • spark-submit:spark-shell底层也是调用spark-submit,如果你想知道它有什么参数,可以直接在spark目录下输入 spark-submit来查看

3.2 流程

这里我们就以 Spark On Yarn 为例来说明

3.2.1 Yarn-Client 模式

流程如下:

  1. 在客户端通过spark-submit向Yarn提交Application
  2. 应用在Client启动Driver,创建SparkContext并进行初始化
  3. ResourceManger为应用申请一个Container来启动Application Master,用来与Client中的SparkContext进行通讯。
  4. Application Master即承担起了为应用申请资源运行Executor的责任,一旦申请到资源,那么就会在指定的NodeManager的Container上创建Executor进程,Executor会向SparkContext注册,保持通讯
  5. SparkContext会根据任务所需资源,数据本地性等条件指定Task的运行在哪个Executor上,将Task分发到指定Executor并开始执行,Executor会周期向SparkContext汇报任务运行情况
  6. 一旦所有任务执行完毕,SparkContext会向ResourceManger申请注销自己并关闭

3.2.2 Yarn-Cluster 模式

流程如下:

  1. 在客户端通过spark-submit向Yarn提交Application
  2. ResourceManger为应用申请一个Container来启动Application Master,并且在Application Master进行SparkContext等初始化。
  3. Application Master即承担起了为应用申请资源运行Executor的责任,一旦申请到资源,那么就会在指定的NodeManager的Container上创建Executor进程,Executor会向SparkContext注册,保持通讯
  4. Applicaiton Master会根据任务所需资源,数据本地性等条件指定Task的运行在哪个Executor上,将Task分发到指定Executor并开始执行,Executor会周期向Applicaiton Master汇报任务运行情况
  5. 一旦所有任务执行完毕,Applicaiton Master会向ResourceManger申请注销自己并关闭

3.3 Job的全生命周期

  • action算子触发
  • 内部实际就是sc.runJob,最终调用了submitJob
  • submit中最终调用了DAGScheduler的submitStage,由最后一个stage往前找,直到parentStage缺失调用submitMissingTask
  • DAGScheduler将TaskSet提交给TaskScheduler执行
  • TaskScheduler中实际调用了submit方法,而该方法是使用远程调用的方式来调用CoraseGraintedExecutorBackend的launchTask方法
  • launchTask则是将包装了Task的TadkRunner丢进线程池中去运行
4 Spark的读写流程

4.1 写入流程

  1. RDD调用compute( )方法进行指定分区的写入。
  2. CacheManager中调用BlockManater判断数据是否已经写入,如果未写则写入。
  3. BlockManager中数据与其他节点同步。(与副本节点通讯)
  4. BlockManager根据存储级别写入指定的存储层。(存储级别决定了数据是存储在内存还是磁盘,或者是两者结合)
  5. BlockManager向主节点汇报存储状态。

4.2 读取流程

  1. RDD调用compute( )方法进行指定分区的读取。
  2. 调用BlockManager的get()进行读取
  • 在本地同步读取数据块,首先看能否在内存读取数据块,如果不能读取,则看能否从Tachyon读取数据块,如果仍不能读取,则看能否从磁盘读取数据块。
  • 如果本地没有数据,就进行远程读取:远程获取调用路径,然后getRemote调用doGetRemote,通过BlockManagerWorker.syncGetBlock从远程获取数据。
5 Spark各组件之间的通信方式和流程5.1 通讯框架

1.6之前

  • Spark在模块间通信使用的是AKKA框架。AKKA基于Scala开发,用于编写Actor应用。
  • Actors是一些包含状态和行为的对象。它们通过显式传递消息来进行通信,消息会被发送到它们的消息队列中。对消息队列中的消息进行处理作出响应
  • RPC是单独通过AKKA实现,数据以及文件传输是采用netty实现,而AKKA底层也是使用Netty来实现的

1.6 后

  • 通过netty封装了一套简洁的类似于AKKA Actor模式的RPC接口,并逐步抛弃AKKA这个重量级框架
  • 2.0 之后,所有的网络功能模块都是通过Netty来实现的

5.2 通讯的简单流程

  • 客户端发送请求消息,经过Encoder加上头信息,通过网络发送给服务端
  • 服务端收到消息之后,经过TransportFrameDecoder进行处理,得到消息类型和消息体,在解析得到具体的请求信息
  • 最后由TransportChannelHandler处理具体的请求信息,根据消息类型判断是否回应
6 Spark的容错机制

分布式系统常用的容错机制

  • 数据检查点:成本高,耗费资源
  • 记录数据的更新:耗费资源较少

Spark所采用的容错机制是记录数据更新和数据检查点相结合的形式。原因如下:

  • RDD只支持粗粒度转换,即在大量记录上执行的单个操作。将创建RDD的一系列Lineage(即血统)记录下来,以便恢复丢失的分区。也就是说当子RDD分区丢失时,只要重新计算它对应的父RDD分区就可以进行恢复,这对于窄依赖来说不存在冗余计算。
  • 宽依赖也就是Shuffle Dependency,也就是发生在shuffle阶段的依赖,如果子RDD分区丢失了,那么重新计算的代价就比较大,因为有多个父RDD分区对应该子RDD分区,那么重新计算时所有的父RDD分区都得重新计算,造成了计算冗余

以下情况需要添加检查点

  • DAG中依赖线过长,如果重算,则开销太大
  • 在Shuffle Dependency上做CheckPoint(检查点)获得的收益更大

在RDD计算中,通过检查点机制进行容错,传统做检查点有两种方式:通过冗余数据和日志记录更新操作。RDD中所采用的就是通过冗余数据来缓存数据,然后对已进行冗余
操作的RDD执行删除该祖先的RDD依赖

官方建议,做检查点的RDD做好先缓存在内存中,否则需要进行重新计算

7 Spark的Shuffle机制

Shuffle中文意思就是混洗,跟MapReduce中的Shuffle的思想是相同,就是数据的重新分区和组合

Spark的Shuffle是在stage的承接阶段完成的,前面的stage会根据后面stage的分区数来将数据按照一定的规则分成相应的bucket,然后写到磁盘上。后续的stage会从元数据那里获得指定数据的所在节点,将数据拉取本地做进一步的操作

Shuffle分为两个阶段

  • Shuffle Write :Shuffle的第一步骤,就是将前一个stage中的数据写到磁盘,用于第二步的Fetch
    • 主要是在ShuffleMapTask中执行(runTask)方法
    • 如果设置了map端进行聚合的话,那么会先执行数据在map的合并,减少网络传输
    • Consolidate Shuffle相比普通Shuffle的优势在:普通shuffle产生的Shuffle文件数为map任务数 x Reduce任务数,而Consolidate Shuffle的理论Shuffle文件数为Spark Core数 x Reducer数,而概念上C_Shuffle引入了文件数组,一个Bucket不再对应一个文件,而是对应文件中的一个segment
  • Shuffle Fetch:通过本地或者远程抓取需要的数据到本节点进行计算,完成操作如保存数据到指定路径或者作为下一个Shuffle的Shuffle Write

Shuffle Aggregator并不会对所有情况下的数据进行排序,所以Aggregator分为不需要外排和需要外排两种方式

  • 不需要外排:数据全部保存在内存当中,使用AppendOnlyMap来进行数据的存储,数据是来一个处理一个,更新到map中,所以reducer的内存必须足够大,能够存储该分区的所有key和count的值
  • 需要外排:reduce类型的操作,内存没办法存放所有的key-value对,必须借助外部磁盘

在Reduce端,各个Task会并发启动多个线程同时从多个Map Task端拉取数据。由于Reduce阶段的主要任务是对数据进行按组规约。也就是说,需要将数据分成若干组,以便以组为单位进行处理。大家知道,分组的方式非常多,常见的有:Map/HashTable(key相同的,放到同一个value list中)和Sort(按key进行排序,key相同的一组,经排序后会挨在一起),这两种方式各有优缺点,第一种复杂度低,效率高,但是需要将数据全部放到内存中,第二种方案复杂度高,但能够借助磁盘(外部排序)处理庞大的数据集。Spark前期采用了第一种方案,而在最新的版本中加入了第二种方案, MapReduce则从一开始就选用了基于sort的方案。
摘抄自董西成的文章链接如下http://dongxicheng.org/framework-on-yarn/apache-spark-shuffle-details/


推荐阅读
  • IOS Run loop详解
    为什么80%的码农都做不了架构师?转自http:blog.csdn.netztp800201articledetails9240913感谢作者分享Objecti ... [详细]
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • com.hazelcast.config.MapConfig.isStatisticsEnabled()方法的使用及代码示例 ... [详细]
  • Java高并发与多线程(二):线程的实现方式详解
    本文将深入探讨Java中线程的三种主要实现方式,包括继承Thread类、实现Runnable接口和实现Callable接口,并分析它们之间的异同及其应用场景。 ... [详细]
  • 本文总结了一些开发中常见的问题及其解决方案,包括特性过滤器的使用、NuGet程序集版本冲突、线程存储、溢出检查、ThreadPool的最大线程数设置、Redis使用中的问题以及Task.Result和Task.GetAwaiter().GetResult()的区别。 ... [详细]
  • 深入探索HTTP协议的学习与实践
    在初次访问某个网站时,由于本地没有缓存,服务器会返回一个200状态码的响应,并在响应头中设置Etag和Last-Modified等缓存控制字段。这些字段用于后续请求时验证资源是否已更新,从而提高页面加载速度和减少带宽消耗。本文将深入探讨HTTP缓存机制及其在实际应用中的优化策略,帮助读者更好地理解和运用HTTP协议。 ... [详细]
  • 本文详细介绍了一种利用 ESP8266 01S 模块构建 Web 服务器的成功实践方案。通过具体的代码示例和详细的步骤说明,帮助读者快速掌握该模块的使用方法。在疫情期间,作者重新审视并研究了这一未被充分利用的模块,最终成功实现了 Web 服务器的功能。本文不仅提供了完整的代码实现,还涵盖了调试过程中遇到的常见问题及其解决方法,为初学者提供了宝贵的参考。 ... [详细]
  • 在Java Web服务开发中,Apache CXF 和 Axis2 是两个广泛使用的框架。CXF 由于其与 Spring 框架的无缝集成能力,以及更简便的部署方式,成为了许多开发者的首选。本文将详细介绍如何使用 CXF 框架进行 Web 服务的开发,包括环境搭建、服务发布和客户端调用等关键步骤,为开发者提供一个全面的实践指南。 ... [详细]
  • 本文介绍了如何利用 Delphi 中的 IdTCPServer 和 IdTCPClient 控件实现高效的文件传输。这些控件在默认情况下采用阻塞模式,并且服务器端已经集成了多线程处理,能够支持任意大小的文件传输,无需担心数据包大小的限制。与传统的 ClientSocket 相比,Indy 控件提供了更为简洁和可靠的解决方案,特别适用于开发高性能的网络文件传输应用程序。 ... [详细]
  • 深入解析C#中app.config文件的配置与修改方法
    在C#开发过程中,经常需要对系统的配置文件进行读写操作,如系统初始化参数的修改或运行时参数的更新。本文将详细介绍如何在C#中正确配置和修改app.config文件,包括其结构、常见用法以及最佳实践。此外,还将探讨exe.config文件的生成机制及其在不同环境下的应用,帮助开发者更好地管理和维护应用程序的配置信息。 ... [详细]
  • 本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。 ... [详细]
  • 本章节在上一章的基础上,深入探讨了如何通过引入机器人实现自动聊天、表情包回应以及Adidas官方账号的自动抽签功能。具体介绍了使用wxpy库进行微信机器人的开发,优化了智能回复系统的性能和用户体验。通过详细的代码示例和实践操作,展示了如何实现这些高级功能,进一步提升了机器人的智能化水平。 ... [详细]
  • 如何使用 `org.eclipse.rdf4j.query.impl.MapBindingSet.getValue()` 方法及其代码示例详解 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 优化后的标题:深入探讨网关安全:将微服务升级为OAuth2资源服务器的最佳实践
    本文深入探讨了如何将微服务升级为OAuth2资源服务器,以订单服务为例,详细介绍了在POM文件中添加 `spring-cloud-starter-oauth2` 依赖,并配置Spring Security以实现对微服务的保护。通过这一过程,不仅增强了系统的安全性,还提高了资源访问的可控性和灵活性。文章还讨论了最佳实践,包括如何配置OAuth2客户端和资源服务器,以及如何处理常见的安全问题和错误。 ... [详细]
author-avatar
书友80922185
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有