经过之前的文章《Spark RDD分区数与分区器源码解析》咱们了解到了什么是 RDD,RDD 能够简略理解为弹性分布式数据集,RDD供给了许多种类的算子,那么使用RDD的这些算子是怎么在分布式环境下去履行的呢?
归根结底,咱们编写的代码是需求经过Spark去协助咱们把使命分布到各个集群上并履行的,那么这一类过程咱们统称为分布式核算,Spark能完成分布式核算功能主要是靠它的进程模型以及调度体系。
一、Spark 进程模型
Spark进程模型一共分为两块,分别是:
Driver: 担任解析用户代码、构建核算流图,并将核算流程拆分为分布式核算使命然后提交给集群去运转,本质上便是一个运转着上述代码逻辑的JVM进程,当咱们提交了一个Spark使用之后,便会启动一个Driver进程。
Executor: 真实担任履行用户代码的进程,在Spark分布式环境里,一个工作节点上会运转多个Executor,然后由多个Executor一同去履行使命代码。
它们之间的关系类似于这样:
那么咱们可能会好奇,Driver详细是怎么解析用户代码并构建核算流图、Executor又是怎么履行使命的呢?就让咱们带着这些问题,详细来看一下Spark的调度体系。
二、Spark调度体系
前面咱们讲到Driver是一个进程,那么这个进程里面还运转着DAGScheduler、SchedulerBackend以及TaskScheduler三个线程,这三个线程各自有各自的功能。
DAGScheduler
DAGScheduler的人物有点类似于架构师,担任将全体体系的架构拆分为一个又一个的项目然后交给其他人去完成,这个全体体系架构便是DAG,DAG全称Directed AcyclicGraph—— 有向无环图。在Spark顶用DAG来描绘咱们的核算逻辑,DAG是一组极点和边的组合,在Spark中极点代表了RDD,边代表了对RDD的一系列操作。在Spark 中引入DAG能够优化核算方案,比方减少Shuffle数据。
那么DAGScheduler的责任便是将核算图DAG以Shuffle为边界拆分为履行阶段Stages,一同将这个Stage转换为TaskScheduler所需求的Task去调度。
SchedulerBackend
SchedulerBackend的人物则有点类似于人力总监,担任实时汇总并把握全公司的人力,全公司的人力对应的便是Spark的核算资源,中心责任便是实时收集集群中可用的核算资源并供给给TaskScheduler用以调度。
这些核算资源都是经过与集群内所有Executor中的ExecutorBackend保持周期性通讯来获取到的,一同内部使用ExecutorDataMap来保存这些集群信息,ExecutorDataMap是一种HashMap,它的Key是每个Executor的字符串,Value则是用于封装Executor的一个目标,这个目标里面会记录RPC地址、主机地址、可用CPU核数等,它相当所以对Executor做的一个描绘,描绘该Executor的资源有哪些。
一同SchedulerBackend会将可调度的资源封装成一个WorkerOffer供给给TaskScheduler核算资源,WorkerOffer封装了ExecutorID、主机地址、CPU核数,用来表明一份可用于调度使命的空闲资源。
TaskScheduler
TaskScheduler从DAGScheduler获取到的每一个使命自身都具有不同的资源分配规则,比方说不同Stages之间,TaskScheduler供给了两种调度形式,FIFO(先到先得)和FAIR(公平调度),而在同一个Stages内的不同使命能够依照本地性级别来分配Executor履行,从PROCESS_LOCAL(同一进程内)、NODE_LOCAL(同一节点内)、RACK_LOCAL(同一物理机内)到ANY(无限制),限制越来越宽松。
TaskScheduler的人物则类似于项目经理,总架构师拆分项目后分配给TaskScheduler,然后TaskScheduler又从人力资源总监SchedulerBackend那里获取到自己可用的组员名单,然后将自己拿到的使命以及名单依照资源来分配规则,安排好每个职工的详细工作之后,再给到SchedulerBackend,SchedulerBackend在将这些使命进一步分配给分公司的人力资源办理ExecutorBackend。
ExecutorBackend
ExecutorBackend作为分公司的人力资源主管,在拿到活之后,会把使命分配给底下的组员,这些组员便是Executors线程池里的一个又一个CPU线程,每个线程担任处理一个Task,处理完之后这些线程便会经过ExecutorBackend奉告SchedulerBackend,SchedulerBackend和TaskScheduler再以接力的方法奉告DAGScheduler,后续再敞开下一轮的Stages核算。
总结
在介绍完Spark的进程模型以及使命调度体系之后,想必咱们对于Spark又有了一个新的知道,把握了这些内容就等于把握了Spark分布式核算的精华,为咱们往后开发高性能代码打下了杰出的根底。但这仅仅冰山一角,Spark自身是一个非常庞大的架构,它衍生出了许多结构,每个结构都有不同的规划理念,都值得咱们去学习,学无止境,让咱们一同学好根底,努力提高自己吧。
注:文章部分参阅来源于网络,如有侵权,请联系删除!
本期内容就到这里了,如果喜爱就点个关注吧,微信公众号搜索 “数 新 网 络 科 技 号” 可查看更多精彩内容~