Spark Core

Spark的架构

  Spark 集群的节点? master、worker
  Spark 采用了分布式计算中的Master-Slave模型。Master作为整个集群的控制器,负责整个集群的正常运行;Worker是计算节点,接受主节点命令以及进行状态汇报。
Spark Core
    Client作为用户的客户端负责提交应用。
    Driver 的功能是创建 SparkContext, 负责执行用户写的 Application 的 main 函数进程,Application 就是用户写的程序。
    SparkContext 负责和 Cluster Manager 通信,进行资源申请、任务分配和监控等。
    Cluster Manager 负责申请和管理在 Worker Node 上运行应用所需的资源,目前包括 Spark 原生的 Cluster Manager、Mesos Cluster Manager 和 Hadoop YARN Cluster Manager。
    每个 Worker 上存在一个或多个 Executor 进程,该对象拥有一个线程池,每个线程负责一个 Task 任务的执行。根据 Executor 上 CPU-core 的数量,其每个时间可以并行多个跟 core 一样数量的Task。Task 任务即为具体执行的 Spark 程序的任务。每个 Application 都有各自独立的一批 Executor。每个 Executor 则包含了一定数量的资源来运行分配给它的任务。每个 Worker Node 上的 Executor 服务于不同的 Application,它们之间是不可以共享数据的。
    Task的执行速度是跟每个Executor进程的CPU core数量有直接关系的。一个CPU core同一时间只能执行一个线程。而每个Executor进程上分配到的多个Task,都是以每个Task一条线程的方式,多线程并发运行的。
    Task是最小的计算单元, 负责执行一模一样的计算逻辑(也就是我们自己编写的某个代码片段),只是每个Task处理的数据不同而已。一个stage的所有Task都执行完毕之后,会在各个节点本地的磁盘文件中写入计算中间结果,然后Driver就会调度运行下一个stage。下一个stage的Task的输入数据就是上一个stage输出的中间结果。如此循环往复,直到将我们自己编写的代码逻辑全部执行完,并且计算完所有的数据,得到我们想要的结果为止。当我们在代码中执行了cache/persist等持久化操作时,根据我们选择的持久化级别的不同,每个Task计算出来的数据也会保存到Executor进程的内存或者所在节点的磁盘文件中。

与 MapReduce 计算框架相比,Spark 采用的 Executor 具有两大优势
    Executor 利用多线程来执行具体任务,相比 MapReduce 的进程模型,使用的资源和启动开销要小很多。
    Executor 中有一个 BlockManager 存储模块,会将内存和磁盘共同作为存储设备,当需要多轮迭代计算的时候,可以将中间结果存储到这个存储模块里,供下次需要时直接使用,而不需要从磁盘中读取,从而有效减少 I/O 开销,在交互式查询场景下,可以预先将数据缓存到 BlockManager 存储模块上,从而提高读写 I/O 性能。

Spark应用的执行流程

Spark Core
    一、启动Master进程和Worker进程:Spark集群启动时,需要主节点和节点分别启动Master进程和Worker进程,对整个集群进行控制。
    二、Driver节点创建SparkContext:在一个Spark应用的执行过程中,Driver是应用的逻辑执行起点,运行Application的main函数并创建SparkContext。
数据源划分为多个分区:Spark 将划分规则抽象为 Partitioner (分区器) ,分区器的核心作用是决定数据应归属的分区,本质就是计算数据对应的分区ID。默认的分区器是 HashPartitioner 哈希分区器(计算公式:将key的hash值除以分区个数,取余数为分区ID)。partition 是逻辑概念,是代表了一个分片的数据,而不是包含或持有一个分片的数据。
    三、RDD划分为多个Stage:DAGScheduler把对Job中的RDD有向无环图根据依赖关系划分为多个Stage,每一个Stage是一个TaskSet。
    四、TaskScheduler把Task分发给Worker中的Executor。
    五、Worker启动Executor,Executor启动线程池用于执行Task。