上文简单对Spark进行了简单介绍,本文旨在进一步对Spark计算引擎进行剖析。
val textFile = sc.textFile(args(1))
val result textFile
.flatMap(line => line.split("\\s+"))
.map(word => (word,1))
.reduceByKey(_+_)
result.saveAsTextFile(args(2))
这是用Scala写的Wordcount的例子(CSDN不能选择插入Scala代码块,所以排版有点问题),步骤比较简单:从HDFS中取数据并转成RDD->flatMap->map->reduceByKey->把数据保存并写回HDFS,显然,和Map-reduce相比,代码量少了很多。
下面来看一下Spark的底层原理:
驱动器(Driver):负责核心协调,调度各个分布式工作节点。
1.把用户程序转化为任务。
2.为执行器节点调度任务。
执行器(Executor):负责在Spark作业中运行任务,各个任务相互独立。
1.负责运行组成Spark应用的任务,并将结果返回给驱动器程序。
2.通过自身的块管理器(Block Manager)为用户程序中要求缓存的RDD提供内存式存储,由于RDD是直接缓存在执行器进程里的,所以可以在运行时充分利用缓存数据提高运算速度。
集群管理器(cluster manager):Spark依赖集群管理器来启动executor节点。
Spark有自带的独立集群管理器,也可以运行在其他外部集群管理器上,如YARN和Mesos等。
下面来简单梳理一下Spark引擎内部执行流程:
1. 生成逻辑查询计划(Logical):通过RDD,创建DAG。
2. 生成物理查询计划(Physical):通过DAG生成物理查询计划,将图分解成一系列stage,每个stage由多个task构成,将task提交到集群中。
3. 任务调度(Schedule):调度并执行Task,通过cluster manager提交作业,之后重新提交失败的task或者拖后腿的task。
4. 任务执行(Execution):分布式执行Task,存储block,提供block读写服务。Task被序列化后,发送到executor上执行。