一、spark工作流程
- 当一个spark应用被提交时,根据提交参数在相应的位置创建driver进程。
- Driver进程启动后,会初始化sparkContext对象,会找到集群master进程,对spark应用程序进行注册
- 当master收到spark程序的注册申请之后,会发送请求给worker,进行资源的调度和分配
- worker收到master的请求后,会为spark应用启动executor进程,会启动一个或多个 executor,具体启动多少个,根据配置来启动
- executor启动之后,会向Driver进行反注册,这样Driver就知道哪些executor为它服务了
- Driver会根据我们对RDD定义的操作,提交一堆的task去Executor上执行,task里面执行的就是具体的map、flatMap这些操作
二、spark的基本概念
- DriverProgram(驱动器):运行main()方法并创建SparkContext的进程
- ClusterManager(也叫master集群管理器) :用于在集群上申请资源的外部服务
- workerNode(工作节点):集群上运行应用程序代码的任意节点
- executor(执行器):在集群工作节点上为某个应用启动的工作进程,该进程负责运行计算任务,并为应用程序存储数据
- job(作业) 一个并行计算作业,由一组任务组成,并由spark的行动(action)算子(save、collect)触发启动,每个Job会根据RDD的宽依赖关系被切分很多Stage,每个Stage中包含一组相同的Task
- stage(阶段) 每个job会被分为多个stage,每个stage是由一组并行的task组成的,stage的划分依据就是看是否产生了shuflle(宽依赖),遇到一个shuflle操作就会划分为前后两个stage
- task:执行器的工作单元
一个Application由一个Driver和若干个Job构成,一个Job由多个Stage构成,一个Stage由多个没有Shuffle关系的Task组成。
三、Spark实战
读取文件中的所有内容,计算每个单词出现的次数
object WorldCountScala {
def main(args: Array[String]): Unit = {
//第一步 创建sparkContext
val conf = new SparkConf()
conf.setAppName("WorldCountScala") //设置任务名称
.setMaster("local") //表示本地执行
val sc = new SparkContext(conf)
//第二步 加载数据
val lineRDD = sc.textFile("D:\\bigdata/hello.txt")
//第三步 对数据进行切割
val wordRDD = lineRDD.flatMap(_.split(" "))
//第四步 迭代words,把每个word转成(word,1)这种形式
// val pairRDD = wordRDD.map(word=>(word, 1))
val pairRDD = wordRDD.map((_, 1))
// 根据key进行分组聚合
val wordCountRDD = pairRDD.reduceByKey(_ + _)
//将结果打印到控制台
wordCountRDD.foreach(wordCount => println(wordCount._1 + "——" + wordCount._2))
//停止sparkContext
sc.stop()
}
运行结果: