注:小学徒从9月1号开始学习scala语言和spark分布式大数据计算框架,现对半个月的学习做出总结,初次了解,多有不足之处,还望各路高手多多指点。
Spark是一个基于内存(优先考虑内存,也可基于磁盘)、擅长进行迭代计算、多数据源的分布式大数据实时计算框架。应用程序提交之后,运行在多台机器上,每台机器各负责处理一部分数据,并行计算,最终进行汇总输出。
多数据源:1.使用程序集合创建RDD
2.使用本地文件系统
3.使用hdfs
4.基于DB创建RDD
5.基于NoSQL(HBase)
6.基于S3创建RDD
7.基于数据流创建RDD
spark集群
1.从sparkruntime角度有五大核心对象:master,worker,executor ,driver ,coarseGrainedExecutorBackend
2.spark做分布式系统设计的时候,最大化功能独立,模块化封装具体独立的对象,强内聚松耦合
3.当driver中的sparkcontext初始化时会提交程序给master,master如果接受该程序在spark中运行时,就会为该程序分配APPID, 同时会分配具体的计算资源,需要特别注意的是,master是根据当前提交程序的配置来给集群中的worker发指令具体的计算资源,但是,master发出指令后并不关心具体的资源是否已分配,master是发指令后就记录分配资源,过后客户端再次提交其他产程序的话, 就不能使用该资源,其弊端是:导致其他提交的程序无法分配到本来应该分配到的资源,优势:在spark分布式系统功能弱耦合 的基础上最快运行系统(否则如果master在资源成功分配后才通知driver,就会造成driver阻塞,不能够最大化并行计算资源的使用率)。
说明:spark在默认情况下由于都只有一个application在运行,spark程序是默认排队的,所以master分配资源的策略的弊端就没有那么明显。
job 提交技巧,在spark-shell中运行了一个job来了解job的提交过程,然后在用源码验证这个过程。
在spark中所有的action至少会触发一个job sparkcontext在实例化的时候会构造SparkDeploySchedulerBackend、DAGScheduler、taskSchedulerImple、MapoutputTrackerMaster等对象.
其中SparkDeploySchedulerBackend负责集群计算资源的管理和调度,
DAGScheduler负责高层调度(例如job中stage划分,数据本地行的内容),
taskSchedulerImple负责具体stage内部的底层调度 (例如具体每个task的调度、task的容错等),
MapoutputTrackerMaster负责shuffle中数据输出和读取的管理 .
TaskSetManager: Starting task 0.0 in stage 0.0 (TID 0, worker, partition 0,NODE_LOCAL, 2125 bytes) 20/09/13 20:36:17 INFO storage.BlockManagerInfo: Added broadcast_1_piece0 in memory on worker:42430 (size: 2.3 KB, free: 517.4 MB) 20/09/13 20:36:18 INFO storage.BlockManagerInfo: Added broadcast_0_piece0 in memory on worker:42430 (size: 19.6 KB, free: 517.4 MB) 20/09/13 20:36:20 INFO scheduler.TaskSetManager: Starting task 1.0 in stage 0.0 (TID 1, worker, partition 1,NODE_LOCAL, 2125 bytes) 20/09/13 20:36:20 I0 NFO scheduler.TaskSetManager: Finished task 0.0 in stage 0.(TID 0) in 5089 ms on worker (1/2)* 20/09/13 20:36:21 INFO scheduler.TaskSetManager: Finished task 1.0 in stage 0.0 (TID 1) in 231 ms on worker (2/2)
task运行在Executor中,而Executor是运行在CoarseGrainedExecutorBackend中,且CoarseGrainedExecutorBackend和 Executor是一一对应的 当CoarseGrainedExecutorBackend接收到TasksetManager发来的launchtask消息后,会反序列化TaskDescription,然后使用且CoarseGrainedExecutorBackend* 中唯一的Executor执行任务
补充说明launchtask是一个case class,每个消息都是一个消息实例
hadoop yarn
1.yarn是hadoop推出的整个分布式(大数据)集群的资源管理器,负责资源的管理和分配,基于Yarn可以在同一个大数据集群上同时运行多个计算框架,例如spark,MapReduce和storm等
2.工作流程:
resource manager管理整个集群的计算资源,根据nodemanger汇报的资源情况,可以知到整个集群上的计算资源 node manager负责管理每个节点上的计算资源,并且向resource manager 汇报当前节点上的内存 及CPU使用状况等计算资源
app Master 当前程序的driver,负责一个运行程序运行
container 向nodemanager汇报资源信息,container要向APPmastr 汇报计算资源
3.客户端向resourcemanager提交application,resourcemanager接收应用并根据几区资源状况决定在那个node上来启动当前应用程序的driver,决定后会命令具体的某个node上的资源管理器nodemanager来启动一个新的jvm进行运行程序的driver,当APP master启动时(会首先向resourcemanager进行注册,说明自己负责当前程序的运行),会下载当前APP相关的jar等各种资源,并基于此决定具体想resource manager申请具体的内容,resource manager接收到APP master分配的资源分配请求后, 会最大化的满足资源分配的请求并发资源的元数据信息发送个诶APP master,APP master收到资源的元数据信息后根据元数据信息发送指令个具体机器上的nodemanager,让nodemanager * 来启动具体的container,container在启动后必须向APP master注册,当APP master获得了计算的containers后,开始进行任务的调度和计算,直到作业的完成。
补充:1. 如果resourcemanager第一次没有能够完全完成app master 分配资源的请求,后续的resource manage发现集群有新的可用资源时,会酌定向APP master发送新的有用的信息用于 * 当前程序的运行。
2.如果container是MapReduce计算的话,不可以复用,如果是spark on yarn可以复用
3.container具体的销毁有APP master来决定的
spark on yarn(不用启动spark集群,只需要启动yarn即可,yarn 的resourcemanager就相当于sparkAlone模式下的master)
两种模式:唯一的决定因素是当前application从任务调度器Driver运行在什么地方,无论什么模式下,只要当前机器运行了spark代码, 就必须安装spark
cluster: driver 运行在yarn集群下的某个机器上的jvm进程中
client driver运行在当前提交程序的客户机器上
spark on yarn 的实战:
client模式:方便在命令终端看到运行的信息,方便测试使用
./spark-submit --class org.apache.spark.examples.SparkPi --master yarn --deploy-mode client ../lib/spark-examples-1.6.0-hadoop2.6.0.jar 1000
standalone 启动spark集群,也就是master和worker,其实启动的是资源管理器,真正做作业计算的时候和集群资源管理器没有任何关系,所以 *spark的job 真正执行作用的不是运行在启动的spark集群中,而是运行在一个jvm中,只要在jvm所在机器上安装配置了spark即可。
spark on yarn 模式下driver和application master的关系:
cluster: driver位于applicationmaster进程中,需要通过hadoop默认指定的8088端口来控制查看当前spark程序运行的信息,例如进度的信息
client: driver为提交代码的机器上,此时applicationmaster依旧位于集群中且只负责资源的申请和lauchExecutor,此时启东后的Executor并不会 * 向Applicationmaster进程注册,而是向driver注册
spark on yarn 的模式下,hadoop yarn配置的yarn.nodemanager.local-dirs会覆盖spark的spark.local.dir!!!
在实际生产环境下一般采用cluster,通过history server来获取最终全部的信息
如果直接运行在日志信息,可以使用 yarn logs-aplicationId <appid>
Spark 核心--SparkContext
spark程序在运行时,分为driver和Executors两部分 。而程序的编写是基于sparkcontext,包含两方面含义:
1. spark程序的核心基础是RDD,是由sparkcontext来创建(第一个RDD一定是由sparkcontext创建的)
2.spark程序的调度的优化也会是基于sparkcontext
而且spark程序的注册是通过sparkcontext来实例化对象来完成的 (其实是schedulerBackend 来注册程序的) spark程序运行时要通过cluster manager获得具体的计算资源,计算资源也是通过sparkcontext产生的对象来申请的 (其实就是schedulerBackend 来获取的) sparkcontext崩溃或者结束的时候整个spark程序也结束了。
即sparkcontext开启了Spark之门,spark程序是通过sparkcontext发布到spark集群上的, sparkcontext导演了spark世界,spark程序的运行都是在以sparkcontext为核心的调度器的指挥下运行的。
sparkContext构建的顶级三大核心对象:DAGScheduler ,TaskScheduler ,ShedulerBackend, 其中:
DAGScheduler 是面向job的stage高层调用
TaskScheduler 是一个接口,根据具体的Clustermanger 的不同会有不同的实现,standalone模式下,具体的实现是TaskSchedulerImpl
ShedulerBackend 也是一个接口,根据具体的Clustermanger 的不同会有不同的实现,standalone模式下,具体的实现是sparkDeploySchedulerbackend
从整个程序运行的角度来讲spark包含四大核心对象: DAGScheduler,TaskScheduler,ShedulerBackend,和MapoutTrackerMaster
其中 sparkDeploySchedulerbackend三大核心功能:
1.负责与master链接注册当前程序
2.接收集群中为当前应用程序而分配的计算资源的注册并管理Executors
3. 负责发送task到具体的Executor执行
说明:sparkDeploySchedulerbackend是被TaskSchedulerImpl管理的。
当通过sparkDeploySchedulerbackend注册程序给master时,会把上述command提交给master,master会发指令给worker 去启动Executor所在进程的时候,加载的main方法所在的入口,入口类就是command中的CoarseGrainedExecutorBackend.当然也可以实现 自己的ExecutorBackend。在CoarseGrainedExecutorBackend中启动Executor,Executor通过线程池并发执行task。
Spark--RDD
RDD实质上就是数据分片,分布在不同的节点上,以partition为单位去管理的,对于开发人员是透明的。编程开发主要针对RDD做处理。其特点如下:
1.自动进行内存和磁盘数据的切换
2.自动基于lineage的高效容错(提供了错误恢复机制)
3.task 失败会自动实现一定次数的重试
4.stage阶段发生失败时,只会提交失败的任务,成功执行的任务不会再次执行
注:1.开发过程中的缓存时机:缓存特别耗时的情况下,计算链条很长,shuffle之后,以及checkpoint
RDD基于工作集的应用抽象---主要基于数据位置、容错和负载均衡
其弹性的缘由如下:1.自动进行内存和磁盘数据的切换
2.基于lineage的高效容错
3.task如果失败会总动进行特定次数的重试
4.stage如果计算失败,会自动进行特定次数的重试,且只计算计算失败的分片
5. checkpoint和数据持久化persist
6. DAG和task资源管理无关
7. 数据分片的高度弹性(repartition)
8.是分布式函数式编程的抽象,计算链条开始不计算(lazy)
RDD通过记录的分布式高效的原因:
1.RDD不可变的lazy构成的计算链条,从后往前,每一级RDD都知道上一个RDD
2.RDD是粗粒度的操作(每次操作都是所有的集合)简化复杂度写操作是粗粒度的但是读操作即可粗粒度也可粒度。
第一个Rdd代表应用程序输入的数据来源,通过transformation来对RDD进行各种算子的转换。
spark Application=driver+executor
其中driver=sparkConf+sparkContext,Executor是运行在worker上为当前进程任务开辟的一个进程,内部是线程池的调用方式