极客时间-吴磊-Spark基础知识一(精简版)

(如需完整版,可转战吴磊老师极客时间付费课程开篇词 | 入门Spark,你需要学会“三步走”-极客时间

Spark 支持种类丰富的开发语言,如 Scala、Java、Python等,尽管不同语言的开发 API 在语法上有着细微的差异,但不论是功能方面、还是性能方面,Spark 对于每一种语言的支持都是一致的,在同样的计算资源下,不同语言代码的执行效率也是一样的;RDD: Spark 对于分布式数据集的抽象,它用于囊括所有内存中和磁盘中的分布式数据实体。
RDD与数组的区别在数组中,承载数据的基本单元是元素,而 RDD 中承载数据的基本单元是数据分片。在分布式计算环境中,一份完整的数据集,会按照某种规则切割成多份数据分片。这些数据分片被均匀地分发给集群内不同的计算节点和执行进程,从而实现分布式并行计算。RDD四大属性partitions:记录 RDD 的所有数据分区(数据分区的数量代表并行度)partitioner:分片切割规则dependencies:RDD 依赖compute:转换函数
算子总述在 Spark 中,创建 RDD 的典型方式有两种:通过 SparkContext.parallelize 在内部数据之上创建 RDD;通过 SparkContext.textFile 等 API 从外部数据创建 RDD。
import org.apache.spark.rdd.RDD // 生成0到99的整型数组val arr = (0 until 100).toArray // 1 使用parallelize生成RDD val rdd = sc.parallelize(arr) // 这里的下划线”_”是占位符,代表数据文件的根目录val rootPath: String = _ val file: String = s”${rootPath}/wikiOfSpark.txt” // 2 读取文件内容 val lineRDD: RDD[String] = spark.sparkContext.textFile(file)
Driver最核心的作用,在于解析用户代码、构建计算流图,然后将计算流图转化为分布式任务,并把任务分发给集群中的 Executors 交付执行。接收到任务之后,Executors 调用内部线程池,结合事先分配好的数据分片,并发地执行任务代码。对于一个完整的 RDD,每个 Executors 负责处理这个 RDD 的一个数据分片子集。每当任务执行完毕,Executors 都会及时地与 Driver 进行通信、汇报任务状态。Driver 在获取到 Executors 的执行进度之后,结合计算流图的任务拆解,依次有序地将下一阶段的任务再次分发给 Executors 付诸执行,直至整个计算流图执行完毕。
并不是一个节点对应一个executor, Executors是JVM进程,一个计算节点,是可以启动多个进程的

系统调度关流程概述DAGScheduler 是任务调度的发起者,把计算图 DAG 拆分为执行阶段 Stages(以 Actions 算子为起点,从后向前回溯 DAG,以 Shuffle 操作为边界去划分 Stages),Stages 指的是不同的运行阶段,同时负责把 Stages 转化为任务集合 TaskSets,DAGScheduler 以 TaskSet 为粒度,向 TaskScheduler 提交任务调度请求。 不同的action触发众多job, 一个Application中可以有很多job,每个job是由一个或多个stage构成的

对于提请执行的每一个 Stage,DAGScheduler 根据 Stage 内 RDD 的 partitions 属性创建分布式任务集合 TaskSet。 stage与taskSet是一一对应的

TaskSet 包含一个又一个分布式任务 Task,RDD 有多少数据分区,TaskSet 就包含多少个 Task。 Task 与 RDD 的分区,是一一对应的

2. TaskScheduler 在初始化的过程中,会创建任务调度队列,任务调度队列用于缓存 DAGScheduler 提交的 TaskSets。

task的属性: taskBinary、partition 和 locs(DAGScheduler 根据数据分区的物理地址设置的,能够代表数据分区所在的节点,或者executor进程ID)

描述了:Task 应该在哪里(locs)为谁(partition)执行什么任务(taskBinary)。
Task属性

TaskScheduler 是按照任务的本地倾向性(本质上是用来区分计算(代码)与数据之间的关系),来遴选出 TaskSet 中适合调度的 Tasks派发给SchedulerBackend。

本地性倾向,在Spark 中的术语:定向到计算节点 – NODE_LOCAL,Task 还可以定向到进程(Executor)-PROCESS_LOCAL(要求对应的数据分区在某个进程(Executor)中存有副本)机架-RACK_LOCAL(仅要求相应的数据分区存在于同一机架即可)任意地址-ANY(Task 对于分发的目的地没有倾向性)本地性倾向则意味着代码和数据应该在哪里“相会”,PROCESS_LOCAL 是在 JVM 进程中,NODE_LOCAL 是在节点内,RACK_LOCAL 是不超出物理机架的范围,而 ANY 则代表“无所谓、不重要”

TaskScheduler 挑选出了适合调度的Tasks,就把这些 Tasks 通过LaunchTask 消息发送给 SchedulerBackend。 SchedulerBackend 同样使用 LaunchTask 消息,把活儿进一步下发给ExecutorBackend。 ExecutorBackend将任务派发给Executors 线程池中一个又一个的 CPU 线程,每个线程负责处理一个 Task。每当 Task 处理完毕,这些线程便会通过 ExecutorBackend,向 Driver 端的 SchedulerBackend 发送 StatusUpdate 事件,告知 Task 执行状态。

3. TaskScheduler 结合 SchedulerBackend 提供的 WorkerOffer(使用硬件资源的机会),按照预先设置的调度策略依次对队列中的任务进行调度。

对于集群中可用的计算资源,SchedulerBackend 与资源管理器(Standalone、YARN、Mesos 等)强绑定,是资源管理器在 Spark 中的代理,用 ExecutorDataMap 的HashMap来记录每一个计算节点中 Executors 的资源状态;

ExecutorDataMap的Key 是标记 Executor 的字符串,Value 是一种叫做 ExecutorData (用于封装 Executor 的资源状态,如 RPC 地址、主机地址、可用 CPU 核数和满配 CPU 核数等等,它相当于是对 Executor 做的“资源画像”)的数据结构。

SchedulerBackend 与集群内所有 Executors 中的 ExecutorBackend 保持周期性通信,双方通过 LaunchedExecutor、RemoveExecutor、StatusUpdate 等消息来互通有无、变更可用计算资源。

调度流程图(如需完整版,可转战吴磊老师极客时间付费课程开篇词 | 入门Spark,你需要学会“三步走”-极客时间)

    THE END
    喜欢就支持一下吧
    点赞5 分享
    评论 抢沙发
    头像
    欢迎您留下宝贵的见解!
    提交
    头像

    昵称

    取消
    昵称表情代码图片

      暂无评论内容