spark core

1.Driver:是运行程序的时候,具有main方法并且创建了sparkcontext,这样的一个环境对象。(两点:main方法,创建spakcontext(他是运行调度的核心)),创建sparkcontext时候要有高层调度器(DAGshuler)、底层调度器(taskshuldler)、shudlerbanukander,之后向mater注册应用程序,然后mater给分配资源,然后就是 运行job
2.应用程序:有两个层面,application=driver+executor,driver的代码就是parkconf+sparkcontext,executor中的代码就是各种算子,也就是说程序代码运行就在driver和executor中
3.executor:是运行在worker所在的节点上,为当前应用程序而开启进程里面的处理对象,这些对象负责具体task的运行,通过线程池并发运行和线程复用

spark 有两种模式:一种是stadalone另一种是cluster 一般是client 因为可以看到更多的交互信息

有专门提交spark程序的机器,这台机器一般一定和spark cluster在同样的网络环境中(由于derver需要频繁的集群的exector进行通信)且其配置和普通的worker一致(意思就是配置不要太低),一般master分配的第一个worker就是dirver,

在实际生产环境下,需要些shell脚本自动化配置和提交程序,当然当前的机器一定安装了spark,只不过是这里安装的spark不属于集群

dirver的核心就是sparkcontext,通信使用的是rpc,rpc使用的akka进行通信。

创建sparkcontext需要创建DAGschedule、TaskSchedule、SchedulerBackend ,在实例化的过程中注册当前的程序给master,master接受注册,如果没有问题,master发送指令给worker为当前程序分配资源(master通过spark-env.sh,程序中的sparkConf,spark-submit 提供的参数,通过这三种方式知道分配多少资源),每个worker节点默认为当前程序分配一个executor,在executor中通过线程池并发执行,具体是worker通过proxy为ExecutorRunner对象实例来远程启动ExecutorBackend进程,ExecutorBackend进程里面有executor,executor里面有线程池,实际在工作的时候会通过TaskRunner来封装task,然后从线程池中获得一个线程进行执行,执行后被回收复用,一般情况下当通过action触发job时,sparkcontext会通过DAGSchedule来把job中的rdd构成的DAG化成stage,每个stage内部的业务逻辑是完全相同的但是处理数据是不用的taskset,taskset交给taskschedule和schedulebackend复制具体task的运行,进行数据本地性(在dag划分的时候就会将task发送到具体数据的本地性,spark最大的特点是数据不动代码动),job中最后一个stage中task为resultTask,产生job的结果,其他前面stage中的task都是shulleMapTask,为下一阶段的stage做数据准备,相当于mapreduce中maper,spark是mapreduce更为精致的实现

整个spark的运行,就是DAGShudler把job划分成不用的stage,提交taskset到Taskschedule,进而提交到executor执行(符合数据本地性),每个task会计算rdd中的一个partition,基于该数据来具体执行我们定义的一系列同一个stage内部的函数,以此类推,直到整个程序运行完成

spark透视job:spark在启动集群的时候有个全局管理器master,负责整个集群资源的分配管理以及接受程序提交并为程序分配计算资源,而每个节点上都有个work process来管理当前机器上的计算资源并向master汇报work还能够正常工作,当应用程序master就会为我们的当前提交的应用程序在每个节点上通过schedulebackend默认分配一个CoarseCrainedExecutorBackend 进程,这个进程默认最运用当前机器的最大cpu和内存,当我们的dirver实例化没有问题时候,dirver本身就会进行任务的调度来驱动CoarseCrainedExecutorBackend 中的executor中的线程来并发执行,

我们说worker process是管理当前节点的cpu和计算资源,实质上是通过master管理每台机器上的计算资源的,
worker节点上有worker process ,他会接受master的指令为当前要运行的应用程序分配CoarseCrainedExecutorBackend进程 ,
计算资源是master发指令给worker process,worker process通过ExecutorRunner孵化出一个CoarseCrainedExecutorBackend进程

我们知道Executor负责计算任务,即执行task,而Executor对象的创建及维护是由CoarseGrainedExecutorBackend负责的,CoarseGrainedExecutorBackend在spark运行期是一个单独的进程

1.数据不动,代码动
2.在一个stage内幕算子为何会流动(pipeline)?首先算子合并,也就是所谓的函数式编程的执行的时候最终进行函数的展开从而把一个stage内部的多个算子合并成为一个大算子(其内部包含了当前stage中所有算子对数据的计算逻辑);其次是由于tranformation操作的Lazy特性!!!在具体算子交给集群的Executor计算之前首先会通过spark framework(DAGScheduler)进行算子的优化(基于数据本地性的pipeline)

一、再次思考pipeline

即使采用pipeline的方式,函数f对依赖的RDD中的数据集合的操作也会有两种方式:

f(record),作用于集合的每一条记录,每次只作用于一条记录

f(records)一次性作用于集合的全部数据

spark采用的是第一种方式,原因:

无需等待,可以最大化的使用集群的计算资源;

减少oom的发生;

最大化的有利于并发(限制它并发执行);

可以精准控制每一个partition本身(Dependency)依赖关系及其内部的计算(compute);

基于lineage的算子流动式函数式编程,节省了中间结果的产生,并且可以最大的恢复;

疑问:会不会增加网络通讯:当然不会,因为pipeline在一个stage内。

二、思考spark job具体的物理执行

Spark application里面可以产生1个或者多个job,例如spark-shell默认启动的时候内部就没有job,知识作为资源的分配程序,可以在里面写代码产生若干个job,普通程序中一般而言可以有不同的action,每个action一般也会触发一个job。(有些action会触发其他action)

Spark是MapReduce思想的一种更加精致和高效的实现。MapReduce有很多具体不同的实现,例如hadoop的marreduce基本的计算流程如下:首先是jvm为对象的并发执行的mapper,mapper中map的执行会产生输出数据,输出的数据会经过partitioner指定的规则放到Local FileSystem中,然后在经由shuffle,sort,aggregate编程Reducer中的reduce的输入,执行reduce产生最终执行结果;hadoop maprduce执行的流程虽然简单,但是过于死板,尤其是在构造复杂算法(迭代)时候非常不利于算法的实现,且执行效率极其低下。

Spark算法构造和物理执行时最最基本的核心:最大化pipeline!
基于pipeline的思想,数据被使用的时候才开始计算,从数据流动的视角来说,是数据流动到计算的位置!!!实质上从逻辑的角度来看,是算子在数据上流动!

从算法构建的角度而言:肯定是算子作用于数据,所以是算子在数据上流动;方便算法的构建!

从物理执行的角度而言:是数据流动到计算的位置!

对于pipeline而言,数据计算的位置就是每个stage中最后的rdd,一个震撼人心的内幕真相就是:每个stage中除了最后一个rdd算子是真实的以外,以前的算子都是假的!!!

由于计算的lazy特性,导致计算从后往前回溯,形成computing chain,导致的结果就是需要首先计算出具体一个stage内部左侧的rdd中本次计算依赖的partition。

三、窄依赖的物理执行内幕

一个stage内部的rdd都是窄依赖,窄依赖计算本身是逻辑上上看是从stage内部最左侧的rdd开始立即计算的,根据computing chain,数据(record)从一个计算步骤流动到下一个计算步骤,以此类推,直到计算到stage内部的最后一个rdd来产生计算结果。

Computingchain(根据依赖建立的)的构建是从后往前回溯,而实际的物理计算是让数据从前往后在算子上流动,直到流动到不能在流动位置才开始计算下一个record。这就导致一个美好的结果:后面的rdd对前面的rdd的依赖虽然是partition级别的数据集合的依赖,但是并不需要父rdd把partition中所有的records计算完毕才整体往后流动数据进行计算,这就极大的提高了计算速率!

四、宽依赖物理执行内幕

必须等到依赖的父stage中的最后一个rdd全部彻底计算完毕,才能够计算shuffle来计算当前的stage!

Rdd中的getDependencies负责确定rdd的之间的依赖关系。

作业:我理解中spark job的物理执行

Job由action触发,在diriver端中dagschedule把依赖划分成stage(taskset),然后再经由taskchedule根据scheduleBackend的掌握资源信息,提交task(partition)在executoe线程池执行。

第24课:

一、到底什么是Shuffle?
Shuffle中文翻译为“洗牌”,需要Shuffle的关键性原因是某种具有共同特征的数据需要最终汇聚到一个计算节点上进行计算。

二、Shuffle可能面临的问题?运行Task的时候才会产生Shuffle。(Shuffle已经融化在Spark的算子中了)
1,数据量非常大
2,数据如何分类,即如何Partition,Hash,Sort,钨丝计算;
3,负载均衡(数据倾斜)
4,网络传输效率,需要在压缩和解压缩之间做出权衡,序列化和反序列化也是要考虑的问题。
说明:具体的Task进行计算的时候尽一切最大可能是数据具备Process Locality的特性,退而求其次是增加数据分片,减少每个Task处理的数据量.

三、Hash Shuffle
1)、Key不能是Array;
2)、Hash Shuffle不需要排序;此时从理论上讲就节省了Hadoop MapReduce中进行Shuffle需要排序时候的时间浪费,因为实际生产环境有大量的不需要排序的Shuffle类型
思考:不需要排序的Hash Shuffle是否一定比需要排序的Sorted Shuffle速度更快(不一定)
- 数据规模小,Hash Shuffle比Sorted Shuffle快(很多)!但是如果数据量大,此时SortedShuffle一般都会比Hash Shuffle快(很多)
3)、每个ShuffleMapTask会根据Key的哈希值计算出当前的Key需要写入的partition,然后把决定后的结果写入单独的文件,此时会导致每个Task产生R(指下一个Stage的并行度)个文件,如果当前的Stage中有M个ShuffleMapTask,则会MR个文件!
注意:Shuffle操作绝大多数情况下都要通过网络,如果Maper和Reducer在同一台机器上,此时只需要读取本地磁盘即可。
Hash Shuffle的两大死穴:第一:Shuffle前会产生海量的小文件于磁盘之上,此时产生大量耗时低效的IO操作;第二:内存不共用!由于内存中需要保存海量的文件操作句柄和临时缓存信息,如果数据处理规模比较庞大的话,内存不可承受,出校OOM等问题!
为了改善上述的问题(同事打开过多文件导致Writer Handler 内存使用过大以及产生过度文件导致大量的随机读写带来的效率纪委底下的磁盘io操作),Spark后来推出了Consalidate机制,来把小文件合并,此时Shuffle时文件产生的数量为cores
R,对于ShuffleMapTask的数量明显多于同时可用的并行Cores的数量的情况下,Shuffle产生的文件大幅度减少,会极大降低OOM的可能;

4)为此Spark推出了Shuffle Pluggable开放框架,方便系统升级的时候定制SHuffle功能模块,也方便第三方系统改造人员根据实际的业务场景来开发具体最佳的Shuffle模块;核心接口ShuffleManager,具体默认实现有HashShuffleManager、SortShuffleManager等;
5)Spark1.6中具体的配置如下:

val shortShuffleMgrNames = Map(
“hash” -> “org.apache.spark.shuffle.hash.HashShuffleManager”,
“sort” -> “org.apache.spark.shuffle.sort.SortShuffleManager”,
“tungsten-sort” -> “org.apache.spark.shuffle.sort.SortShuffleManager”)
val shuffleMgrName = conf.get(“spark.shuffle.manager”, “sort”)

第25课:

6)Spark1.6默认采用的就是Sort-based Shuffle的方式
val shuffleMgrName= conf.get(“spark.shuffle.manager”,”sort”)
上述的源码说明:你可以在Spark的配置文件中配置Spark框架运行时要使用的具体的ShuffleManager的实现
修改conf/spark-default.conf,加入以下内容:spark.shuffle.manager SORT 具体ShuffleManager方式(Sort、Hash、钨丝等)
Sort-based Shuffle 不会为每个Reducer中的Task生成一个单独的文件,相反,Sort-based Shuffle会把Mapper中每个SuffleMapTask所有的输出数据Data只写到一个文件中,因为每个ShuffleMapTask中的数据会被分类,所以Sort-based Shuffle使用index文件存储具体ShuffleMapTask输出数据在同一个Data文件中是如何分类的信息!!所以说基于Sort-based的Shuffle会在Mapper中的每一个ShuffleMapTask中产生两个文件:Data文件和Index文件,其中Data文件是存储当前Task的Shuffle输出的,Index文件中则存储了数据Data文件中数据通过Partitioner的分类信息,此时下一个阶段的Stage中的Task就是根据这个Index文件获取自己所要抓取的上一个Stage中的ShuffleMapTask产生的数据的。

Sort-based Shuffle会产生2M(M代表Mapper阶段中并行的Partition的总数量,其实就是Mapper端ShuffleMapTask的总数量)个Shuffle临时文件
回顾整个Shuffle的历史,Shuffle产生的临时文件的数量的变化依次为:
Basic Hash Shuffle:MR;
Consalidate方式的Hash Shuffle:C
R;
Sort-based Shuffle: 2M;

2、在集群中动手实战Sort-based Shuffle
通过动手实践确实证明了Sort-based Shuffle产生了2M个文件

在Sort-based Shuffle中的Reducer是如何获取自己需要的数据的呢?具体而言,Reducer首先找Driver去获取父Stage中每个ShuffleMapTask输出的位置信息,根据位置信息获取index文件,解析index文件,从解析的index文件中获取Data文件中属于自己的那部分内容

3、默认Sort-based Shuffle的几个缺陷
1)如果Mapper中Task的数量过大,依旧会产生很多小文件;此时在Shuffle传递数据的过程中到Reducer端,reduce会需要同时打开大量的记录来进行反序列化,导致大量的内存消耗和GC的巨大负担,造成系统缓慢甚至崩溃
2)如果需要在分片内进行排序的话,此时需要进行Mapper端和Reducer端的两次排序!!!

hadoop mapper有数组代表的环形内存缓存区(有数据也有索引)

第26课: Spark Runtime(Driver、Masster、Worker、Executor)内幕解密

坚持梦想,永不放弃!

本节从Spark Runtime全局的角度看Spark具体怎么工作的,从一个作业的视角通过Driver、Masster、Worker、Executor等角色来透视Spark的Runtime。本节内容包括:1、再论Spark集群部署;2、Job提交解密;3、Job的生成和接受;4、Task的运行;5、再论Shuffle。

(1)从Spark Runtime的角度来讲,包括五大核心对象:Master、Worker、Executor、Driver、CoarseGrainedExecutorBackend;

(2)Spark在做分布式集群系统设计的时候:最大化功能独立、模块化封装具体独立的对象、强内聚松耦合。

(3)当Driver中的SparkContext初始化的时候会提交程序给Master,Master如果接受该程序在Spark中运行的话,就会为当前的程序分配AppID,同时会分配具体的计算资源,需要特别注意的是,Master是根据当前提交程序的配置信息来给集群中的Worker发指令分配具体的计算资源,但是,Master发出指令后并不关心具体的资源是否已经分配,转来说Master是发指令后就记录了分配的资源,以后客户端再次提交其它的程序的话就不能使用该资源了。其弊端是可能会导致其它要提交的程序无法分配到本来应该可以分配到的计算资源;最终的优势在Spark分布式系统功能若耦合的基础上最快的运行系统(否则如果Master要等到资源最终分配成功后才通知Driver的话,就会造成Driver阻塞,不能够最大化并行计算资源的使用率)。需要补充说明的是:Spark在默认情况下由于集群中一般都只有一个Application在运行,所有Master分配资源策略的弊端就没有那么明显了。

第27课
http://bbs.pinggu.org/thread-4637621-1-1.html

第28课
https://www.cnblogs.com/jcchoiling/p/6427406.html

第29课
https://www.cnblogs.com/jcchoiling/p/6427862.html

第30课
https://www.cnblogs.com/jcchoiling/p/6428223.html

第31课
https://www.cnblogs.com/jcchoiling/p/6428606.html

第32课
https://www.cnblogs.com/jcchoiling/p/6433196.html

第33课
https://www.cnblogs.com/jcchoiling/p/6436185.html

第34课
https://www.cnblogs.com/jcchoiling/p/6438435.html

第35课
https://www.cnblogs.com/jcchoiling/p/6464128.html

第36课
https://www.cnblogs.com/jcchoiling/p/6479208.html

第37课
https://www.cnblogs.com/jcchoiling/p/6493133.html

第38课
https://www.cnblogs.com/jcchoiling/p/6507162.html

第39课

第40课
https://www.cnblogs.com/jcchoiling/p/6510969.html

第41课
https://www.cnblogs.com/jcchoiling/p/6513569.html

第42课
https://www.cnblogs.com/jcchoiling/p/6538780.html

初步总结:

1.将程序打包成jar到集群上运行
2.首先是注册程序到master上进行初始化sparkContext:
sparkDeployScheduleBackend资源分配:master接受注册后,会根据三种方式(spark-env.sh,spark-submit 提交时的配置,程序里sparkConf的参数)的参数来发送指令给worker进行粗粒度的分配资源
worker初始化启动与executor交互的进程:worker还需要通过proxy为executoRunner对象实例启动executorBackend进程,并在进程里创建executor线程池,缺点是master分配完,就会默认的分配成功,不会为其他程序分配本应该能分配的计算资源(如分配失败,master不会把这个分配的资源给其他程序)。优点是弱耦合的基础上最快的运行参数(否则如果master要等到资源最终分配成功后才通知dirver了话,就会造成dirver阻塞,不能够最大化并行计算资源的使用率)
DAGschudle :DAG划分的时候通过位置感知进行数据本地性
TaskSchulder :TaskSchulder把每个stage中的taskset分配到各个worker节点上的
SchedulerBackend:task到达work之后,通过schedulebackend(是与executor进行通信的)远程启动ExecutorBackend(CoarseCrainedExecutorBackend)进程:ExecutorBackend进程里面有executor,executor里面有线程池,实际在工作的时候会通过TaskRunner来封装task,然后从线程池中获得一个线程进行执行TaskRunner的run()方法。CoarseCrainedExecutorBackend与executor是一一对应的,也就是配置一个work两个executor,也就是启动两个CoarseCrainedExecutorBackend进程
MapOutputTrackerMaster:负责shuffle中输出和读取的管理,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值