• 3.2 Spark运行架构


    一、基本概念

    1.RDD

    Resillient Distributed Dataset 弹性分布式数据集

    2.DAG

    反映RDD之间的依赖关系

    3.Executor

    进程驻守在机器上面,由进程派生出很多的线程,然后去执行任务。

    4.应用application

    5.任务

    6.作业Job 

      一个应用程序提交之后,会生成若干个作业,每个作业,会被切分成很多个任务子集,每个任务子集叫一个阶段。所以说一个作业包含多个RDD以及作用于相应RDD上的各种操作。

    7.阶段stage

      阶段是作业的基本调度单位,一个阶段是很多个任务的集合

    二、架构设计

    1.Driver program

    功能:任务控制节点,应用程序的“指挥所”

    2.Cluster Manager

    功能:集群资源管理器

    3.Worker Node 工作节点

     每个工作节点都会有executor进程,每个进程派生出多个线程,每个线程具体去执行相关的任务。

      一个应用在执行时候,需要一个管家节点(任务控制节点Driver),然后应用会根据相关代码,最终会被生成若干个作业,一个应用提交以后,它会被分成很多作业,具体生成多少个作业是取决于里面的相关代码。

      一个任务会被切分成不同的作业,一个作业会被切分成不同的阶段,每一个阶段包含了很多个任务,这些任务会被派发到不同的工作节点上,就是workernode去执行。

      每次去执行应用时,Driver节点会向集群的资源管理器申请资源,因为计算需要CPU内存,申请到资源以后,就会启动相对应节点的Executor进程,然后会向对应节点的Executor进程去发送应用程序代码和文件,就在它上面派发出线程去执行具体任务。

    执行结束后, 会把运行结果再返回给Drive节点,然后返回给用户,或者写入到文件系统HDFS或者数据库

    三、Spark运行基本流程

    (1)首先去构建起一个基本的运行环境,要构建集群,应用程序提交的时候要先给它确定运行应用的主节点(Driver节点),一旦确定好(指挥所建好之后),会由Driver节点给它派生一个SparkContext对象。

    (2)这个对象负责向资源管理器申请资源,然后负责把整个作业分解成不同阶段,并且把每个阶段的任务把它调度到不同的节点上面去执行。执行过程它还要进行监控,万一失败了,他要负责恢复回来。

    资源管理器收到资源请求后,会为Executor的进程去分配资源(CPU、内存)去执行,之后启动Executor进程

    executor进程是驻留在各个不同的workernode上面的,可能有几百上千台机器workernode上面

    (3)SparkContext对象要根据RDD的依赖关系构建一张DAG图

    这个图会被提交到叫DAG Scheduler的模块进行解析,它要负责把这张完整的DAG图,把它切成很多不同的阶段,每个阶段里面都包含若干个任务,每个阶段里面都包含多干个任务

    得到一个又一个阶段以后,再把这么一个阶段提交给下一个Task Scheduler,task scheduler具体负责把任务到底分发到哪个节点上面去。整个分发过程并不是说task scheduler拿到任务就往外扔,而是各个worker node上面那些executor会主动地向这个task tracker去申请运行任务。然后task tracker就会把相关的任务,根据它申请的情况,扔到相对应的worker node上,让executor进程去派送线程去执行。

     

    任务分发的基本原则:必须要保证计算向数据靠拢

    数据在哪个节点上面,就优先把计算扔到数据所在节点,完成本地化的处理

    (4)任务在executor上面运行以后,它会得到结果,结果又反馈给TaskScheduler,再用Task Scheduler往上传递给DAG Scheduler,然后由Spark Context对象再做一个最后的处理,或者返回给用户看,或者写入到HDFS。

    Spark Context是整个运行程序的指挥官,而且,它也代表了整个应用程序连接集群的通道。

     

    四、RDD的设计与运行原理

    为什么要有RDD?

      Hadoop处理不了迭代式场景,每次都要从磁盘读取或写入数据,这对于频繁去访问某个数据集的场景不适用的,这会产生很大的磁盘IO开销,还会带来序列化和反序列化开销()。

     

    序列化:本来在内存中生成了Java对象,现在要把它写到磁盘,肯定不能以对象来写,要把他写成二进制或者字符串,比如说想把Java对象传递给另一台机器,或者保存到磁盘里面去,要么写成JSON格式文件传输过去,要么写成二进制文件传输过去,肯定不会把对象传过去。所以,把对象转成可以保存的和传输的格式的过程就叫序列化

    1.RDD运行原理(设计背景)

    RDD提供了抽象的数据结构,就是不用担心底层数据的分布特性,只需要把具体应用逻辑表达成一系列转换,然后不同的RDD之间转换,形成依赖关系,形成一个DAG图。形成DAG图,是可以实现优化的,它生成图的目的,是为了后期实现可能的优化,有可能它优化不了,但很多情况下都是可以优化的。优化就是实现管道化或叫流水线化

    流水线化可以避免数据落地,不用不断地写底层磁盘,就形成流水线。这个操作一结束,马上把操作的输出,作为另外一个操作的输入,不用写到磁盘交给另外一个操作。所以说,有了RDD这种设计的抽象之后,再用DAG这种形式去组织以后,可以发现在很大程度上就可以避免数据频繁落地(“磁盘”)。

    2.RDD概念

    RDD本质上是一个只读的分区记录集合。比如,一个很大的数据集文件,原来是保存在磁盘上面,把它读进来,加载到内存当中生成一个RDD,数据集很大,单机内存肯定放不下,需要把一个RDD非常很多个分区,每个分区放在不同的机器上,比如,分区1放在机器1,分区2放在机器10,这样就变成一个分布式的对象集合,所以一个RDD在逻辑上是一个完整的抽象,但实际上它的数据会被分区,不同的分区会被放到不同机器上。所以说,每个RDD的每个分区就是一个数据片段集合,是一个子集。

     RDD提供了一种高度受限(只读)的共享内存模型,一旦把RDD加载进来,生成内存当中的数据集合,一生成就不能修改这叫高度受限,

     

    RDD是在转化的过程中可以改,但一旦生成新RDD,这个RDD又是不能改的。

    3.RDD操作

    (1)转换类操作

    只记录转换的轨迹,不发生计算

    RDD提供粗粒度的转换操作:map、filter、groupby、join

    粗粒度修改:一次只能针对RDD全集进行转换,不支持有针对性的转换( spark不支持细粒度修改,如网页爬虫。)

    高度受限的共享内存模型会不会影响表达能力?

    (2)动作类型操作

    进行从头到尾的计算

     

    流水线优化:整个操作过程中,一个操作的输出就可以直接形成流水线,交给另外一个操作作为输入,不要去落磁盘。不需要保存中间结果。

    4.RDD特性

    (1)高效的容错性:数据丢失能恢复

    (2)性能高效:数据在内存的多个RDD之间进行传递,避免不必要的读写磁盘开销。从而避免不必要的序列化和反序列。

    5.RDD之间的依赖关系

    疑问:为什么要切,怎么切?

    洗牌(shuffle):过程需要大量网络之间的数据分发。

    (1)怎么划分阶段?

    窄依赖:不划分阶段

    父亲对儿子,一一对应的分区关系,或者是多个父亲RDD对应一个儿子RDD的分区

    宽依赖: 划分成多个阶段。只要发生了shuffle操作,肯定是宽依赖。

     一个父RDD的分区对应一个儿子RDD的多个分区,发生shuffle操作。

    6.阶段的划分

    把一个作业(DAG图)划分成多个阶段,依据就是窄依赖和宽依赖。宽依赖没办法优化,而窄依赖是可以进行优化。

    优化原理:fork和join机制 

    为了能够并行执行,把分区1,分区2和分区3,fork到不同的机器上去,执行完之后再把这几台机器执行的结果join起来。

     

     

     

    7.RDD的运行过程

    (1)创建RDD对象

    (2)SparkContext会计算RDD之间依赖关系,生成一个DAG图

    (3)DAGScheduler会把DAG图分解成很多个阶段,每一个阶段都包含了若干了任务集合,这些任务会被Task Scheduler调度,扔给不同的Worker Node去执行。Worker Node上面有Excutor进程,每一个Excutor进程都会派生出很多的线程,每个线程就会具体去执行任务,最终把任务再发返回给Task Scheduler,再由DAGScheduler提交给SparkContext,再由SparkContext对象将结果返回用户或写入磁盘。

    参考文献:

    【1】Spark编程基础_中国大学MOOC(慕课)

  • 相关阅读:
    16.如何使用ForkJoinPool?
    zookeeper window安装
    5.run方法和start方法的区别
    6.获取和设置线程优先级
    17. 如何使用CompletionService?
    SpringBoot 线程池 配置使用
    Spring中常用工具类
    SpringBoot下@EnableAsync与@Async异步任务的使用
    @EnableAsync@Async使用总结
    SpringBoot异常处理
  • 原文地址:https://www.cnblogs.com/nxf-rabbit75/p/11766691.html
Copyright © 2020-2023  润新知