Spark运行原理&相对mapreduce优势
一. 相对mapreduce优势
Spark 与 mapreduce 的重要概念区别
mapreduce
- 一个 mapreduce 就是一个job
- 一个job 包含N个task ( Map Task /Reduce Task)
- 一个task 对应一个进程
- Task运行开启进程, task完毕后销毁进程, 对于多个task而言, 开销是比较大的
Spark
Application = Driver(mian中创建SparkContext) + Executors
一个Application = 0或多个 job
一个job = 1个action
一个job = 1到N个Stage (宽窄依赖划分)
一个stage = 1到N个Task = 1个TaskSet
一个Task对应一个线程, 多个task可以以并行的方式运行在一个Executor进程中
spark中task 分为两种:
1)result task类型,最后一个task。
2)是shuffleMapTask类型,除了最后一个task都是。
为什么Spark强于mr?
spark是基于内存运算的, 中间结果在内存足够的情况下,会优先放在内存中,从而避免磁盘IO。
mapreduce 每一次shuffle 中间都需要落地带来磁盘IO。
spark 具有DAG只有在遇到 action 算子的时候才会shuffle(1个job)。 job较少 减少需要缓存或落地的次数。
mapreduce 一个 mapreduce 就是一个job,job较多 job间依赖落地增加磁盘IO次数。
spark是粗粒度资源申请,也就是当提交spark application的时候, application会将所有的资源申请完毕,如果申请不到资源就等待,如果申请到资源才执行application,task在执行的时候就不需要自己去申请资源,task执行快,当最后一个task执行完之后task才会被释放。
MapReduce是细粒度资源申请,当提交application的时候,task执行 时,自己申请资源,自己释放资源,task执行完毕之后,资源立即会被释放,task执行的慢,application执行的相对比较慢。
二. Spark的运行模式 :
- local 多用于测试 单机
- Standalone Spark集群中 可以i抛开hadoop集群环境,独立的Spark提供的环境,Spark提供的独立资源调度
- Messo 一种更细力度的资源划分方式
- yarn 广泛运用的
Spark 的运行模式:
-
local 不需要集群 解压在bin文件夹下即可使用
任务提交: ./bin/spark-submit --class org.apache.spark.demo.SparkPi --master local[1] ./lib/spark-examples-1.6.0-hadoop2.4.0.jar 100 --class 类 --master [1]表示线程数 执行的jar包 100 参数
-
standalone 模式 独立模式, Spark 原生的简单集群管理器, 自带完整的服务,可单独部署 到一个集群中,无需依赖任何其他资源管理系统 ,其资源管理用的是spark 自己提供的,抛开hadoop
主从: master -- worker ./bin/spark-submit --class org.apache.spark.demo.SparkPi --master spark://park2:7077 --executor-mermory 1G --total-executor-cores 1 ./lib/spark-examples-1.6.0-hadoop2.4.0.jar 100 --master master所在的机器 --executor-mermory 一个work中起的进程的内存 --total-executor-cores 所有executor(application)所占的核数
standalone有两种模式: 1. client 模式, Driver 进程在本地 结果日志可在xshell中可见 2. cluster 模式 ./bin/spark-submit \ --class org.apache.spark.demo.SparkPi --master spark://park2:7077 --deploy-mode cluster --executor-mermory 1G --total-executor-cores 1 ./lib/spark-examples-1.6.0-hadoop2.4.0.jar 100 结果在xshell中不显示,在页面中会有显示
-
spark on yarn
./bin/spark-submit \ --master yarn-client \ --deploy-mode client \ --driver-cores 2 \ # driver使用内核数,默认为1 --driver-memory 8g \ # driver内存大小,默认512M --executor-cores 4 \ # 每个executor使用的内核数,默认为1 --num-executors 10 \ # 启动executors的数量,默认为2 --executor-memory 8g \ # executor内存大小,默认1G --class org.apache.spark.demo.SparkPi ./lib/spark-examples-1.6.0-hadoop2.4.0.jar 100 ---- 说明 ---- ~ 1. --master yarn-client #表示 启用client模式 Driver 进程在本地, Executor进程在 Yarn 集群 上,部署模式必须使用固定值:--deploy-mode client。 Yarn 集群地址必 须在HADOOP_CONF_DIR or YARN_CONF_DIR 变量里定义。 --master yarn-cluster #表示 启用cluster模式 Driver 进程在 Yarn 集群上, Work进程也在 Yarn 集群上,部署模式必须使用固定值:--deploy-mode cluster。 Yarn 集群地 址必须在HADOOP_CONF_DIR or YARN_CONF_DIR 变量里定义 ~ 2. 如果这里通过--queue 指定了队列,那么可以免去写--master
设置参数
- executor_cores*num_executors
表示的是能够并行执行Task的数目 不宜太小或太大!一般不超过总队列 cores 的 25%,比如队列总 cores 400,最大要超过100,最小不建议低于 40,除非日志量很小。 - executor_cores 不宜为1 否则 work 进程中线程数过少,一般 2~4 为宜。
- executor_memory
一般 6~10g 为宜,最大不超过20G,否则会导致GC代价过高,或资源浪费 严重。 - driver-memory
driver 不做任何计算和存储,只是下发任务与yarn资源管理器和task交 互,除非你是 spark-shell,否则一般 1-2g
- executor_cores*num_executors
三. spark 运行原理
1. 运行流程
standalone 在 Client模式: 参考自
application启动之后, 会在本地启动一个Driver进程 用于控制整个流程,(假设我们使用的Standalone模式)
首先需要初始化的是SparkContext, SparkContext 要构建出DAGScheduler,TaskScheduler
在初始化TastScheduler的时候,它会去连接master,并向master 注册Application ,master 收到信息之后,会调用自己的资源调度算法,在spark集群的work上,启动Executor,并进行资源的分配, 最后将Executor 注册到TaskScheduler, 到这准备工作基本完成了
现在可以进行我们编写的的业务了, 一般情况下通过sc.textFile(“file”) 去加载数据源( 这个过程类似于mr的inputformat加载数据的过程), 去将数据转化为RDD,
DagScheduer 先按照action将程序划分为一至多个job(每一个job对应一个Dag), 之后对DagScheduer按照是否进行shuffer,将job划分为多个Stage 每个Stage过程都是taskset , dag 将taskset交给taskScheduler,由Work中的Executor去执行, 至于tast交给那个executor去执行, 由算法来决定,
如果是基于yarn 的client:
- 在YARN Client模式下,Driver在任务提交的本地机器上运行,Driver启动 后会和ResourceManager通讯申请启动ApplicationMaster,随后ResourceManager分配container,在合适的NodeManager上启动 ApplicationMaster,此时的ApplicationMaster的功能相当于一个 ExecutorLaucher,只负责向ResourceManager申请Executor内存。
- ResourceManager接到ApplicationMaster的资源申请后会分配 container,然后ApplicationMaster在资源分配指定的NodeManager上 启动Executor进程,Executor进程启动后会向Driver反向注册.
- Executor 全部注册完成后Driver开始执行main函数,之后执行到Action算子时,触发一个job,并根据宽依赖开始划分stage,每个stage生成对应的 taskSet,之后将task分发到各个Executor上执行。
如果是基于yarn 的cluster:
- 在YARN Cluster模式下,任务提交后会和ResourceManager通讯申请启 动ApplicationMaster,随后ResourceManager分配container,在合适的NodeManager上启动ApplicationMaster,此时的ApplicationMaster 就是Driver。
- Driver启动后向ResourceManager申请Executor内存, ResourceManager接到ApplicationMaster的资源申请后会分配 container,然后在合适的NodeManager上启动Executor进程, Executor进程启动后会向Driver反向注册.
- Driver开始执行main函数,之后执行到Action算子时,触发一个job,并根 据宽依赖开始划分stage,每个stage生成对应的taskSet,之后将task分发 到各个Executor上执行。
2. 组件概念介绍
Driver: 一个Spark作业运行时包括一个Driver进程,也是作业的主进程,负责作业的解析、生成Stage并调度Task到Executor上。包括DAGScheduler,TaskScheduler。
SparkContext:连接到spark集群, 入口
DAGScheduler:实现将Spark作业分解成一到多个Stage,每个Stage根据RDD的Partition个数决定Task的个数,然后生成相应的Task set放到TaskScheduler中。
Dag(有向无环图): 根据action进行划分形成的job, 为啥叫叫做Dag ,因为DagScheduler根据会根据shuffer将这个job划分为多个Stage , 阶段的划分,使job的流程更加清晰,
Stage(阶段) :是task的集合,计算job中的中间结果。同一RDD的每个分区都会应用相同的计算函数。在shuffle的边界处进行隔离(因此引入了隔断,需要上一个stage完成后,才能得到output结果) 有两种类型的stage:
1). ResultStage,用于执行action动作的最终stage。
2). ShuffleMapStage,对shuffle进行输出文件的写操作的。如果job重用了同一个rdd的话,stage通常可以跨越多个job实现共享。
TaskScheduler:底层的调度器,唯一实现TaskSchedulerImpl。可插拔,同Dag调度器接受task,发送给cluster, 运行任务,失败重试,返回事件给DAG调度器。
Task:单独的工作单元,在worker节点上的Executor内执行。
Executor: spark程序执行者,通过线程池执行任务。
Transformation: 用于对RDD的创建,RDD只能使用Transformation创建,同时还提供大量操作方法,包括map,filter,groupBy,join等,RDD利用这些操作生成新的RDD,但是需要注意,无论多少次Transformation,在RDD中真正数据计算Action之前都不可能真正运行。
Action: 是数据执行部分,其通过执行count,reduce,collect等方法真正执行数据的计算部分。实际上,RDD中所有的操作都是Lazy模式进行,运行在编译中不会立即计算最终结果,而是记住所有操作步骤和方法,只有显示的遇到启动命令才执行。这样做的好处在于大部分前期工作在Transformation时已经完成,当Action工作时,只需要利用全部自由完成业务的核心工作。