(一)spark RDD的依赖关系
1.窄依赖
窄依赖指的是每一个父RDD的Partition最多被子RDD的一个Partition使用
比喻:独生子女
结论:窄依赖不会产生shuffle
比如:flatMap/map/filter…
2.宽依赖
窄依赖指的是父RDD的Partition被子RDD的多个Partition使用
比喻:超生
结论:宽依赖会产生shuffle
比如:reduceByKey/groupByKey…
(二)lineage(血统)
spark任务在进行计算的时候,会有大量的rdd相关操作,记录这些rdd的操作记录的信息就lineage(血统)
血统的好处:
当前某一个rdd的分区数据丢失了,后期可以通过血统这一层关系重新计算恢复得到。
(三)RDD的缓存机制
1.rdd的缓存是什么
如果后期某一个rdd的数据,需要多次去使用,
这个时候就可以把当前rdd的结果数据进行缓存,
缓存之后后期需要份结果数据可以直接从缓存中获取得到,
避免重新计算。
2.如何对rdd设置缓存
cache 或者 persist
后面需要一个action操作,才会触发缓存的执行
3.cache和persist区别
cache:
默认把数据缓存在内存中,其本质是调用了persist方法
persist:
它可以把数据缓存在磁盘中,它可以有很多丰富的缓存级别,这些缓存级别都被封装在一个RDD object StorageLevel
//开启shell脚本测试
[root@node01 spark-2.2.0-bin-hadoop2.7]# spark-shell --master spark://node01:707
//web界面查看
http://node01:8080/
scala> val rdd1 = sc.textFile("/sparkdata/input/word.txt")
//cache缓存
scala> rdd1.cache
scala> rdd1.collect
scala>
scala>
scala> val rdd2=rdd1.flatMap(_.split(" "))
//persist缓存
scala> rdd2.persist(org.apache.spark.storage.StorageLevel.DISK_ONLY)
scala> rdd2.collect
scala>
4.清除缓存
1)自动清除
整个程序结束之后,缓存中的所有数据自动清除
2)手动清除
手动调用rdd的unpersist(true)
5.什么时候设置缓存
1)某个rdd的结果数据被使用很多次
2)结果数据计算逻辑比较复杂或者计算时间长长的
(四)DAG有向无环图的生成
1.为什么要划分stage
每个stage只有窄依赖,没有宽依赖,
在每一个stage中都有很多可以并行运行的task,互不影响
2.如何划分stage—宽依赖是依据
1)从最后一个rdd往前推,首先产生一个stage,然后把最后一个rdd加入到stage中,它就是最后一个stage
2)如果遇到窄依赖就把该rdd加入到stage中,如果遇到宽依赖,就从宽依赖切分,最后一个stage也就结束了
3)重新生成一个新的stage,按照第二步的逻辑继续往前推,一直推到最开始的rdd,整个划分stage也就结束了
3.内部逻辑
每一个stage中有很多可以并行运行的task,把这些task都封装在taskSet中
rdd与rdd间存在依赖关系,stage与stage之间也存在依赖关系
按stage的先后顺序运行里面的task,前stage的task输出数据是后stage的task输入数据
开发一个saprk的应用程序application,
一个action就是一个job,
一个application包括多个action,
也就是说一个application会存在多个job
每一个job都会存在一系列转换操作,
最后每一个job都会生成一个有向无环图,
并且会存在大量的宽依赖,
每个DAG有向无环图的划分就是以宽依赖为依据的,
最后一个application应用程序会产生大量的task。
(五)Spark的任务调度
1. Spark任务调度流程图
2. DAGScheduler介绍
- DAGScheduler对DAG有向无环图进行Stage划分。
- 记录哪个RDD或者Stage输出被物化(缓存),通常在一个复杂的shuffle之后,通常物化一下(cache、persist),方便之后的计算。
- 重新提交shuffle输出丢失的stage(stage内部计算出错)给TaskScheduler
- 将Taskset传给底层调度器
- spark-cluster TaskScheduler
- yarn-cluster YarnClusterScheduler
- yarn-client YarnClientClusterScheduler
3. TaskScheduler介绍
- 为每一个TaskSet构建一个TaskSetManager 实例管理这个TaskSet 的生命周期
- 数据本地性决定每个Task最佳位置
- 提交 taskset( 一组task) 到集群运行并监控
- 推测执行,碰到计算缓慢任务需要放到别的节点上重试
- 重新提交Shuffle输出丢失的Stage给DAGScheduler
(六)spark容错机制之checkpoint
1.什么是checkpoint
之前了解的rdd缓存机制,cache/persist
catch:
默认把数据缓存在内存中,不是非常安全,如果当前进程挂掉或者宕机了,内存中的数据就会丢失。
persist:
可以把数据缓存在本地磁盘,里面有很多的缓存级别,相对于catch来说,后期操作起来比较慢,需要大量的io操作,这里比catch稍微安全一点,但不是绝对安全,后期磁盘损坏或者是系统管理员由于一些误操作把磁盘中的数据清除了,最后也会导致数据丢失
checkpoint:
它是提供了一个相对而言更加可靠持久化数据方法,它可以把数据写入到分布式文件系统中(HDFS),利用hdfs的高容错性(多副本机制)最大程度来保证数据安全性。
2.如何设置checkpoint
1)在hdfs上设置/sparkdata/ck2018目录
- sc.setCheckpointDir("/sparkdata/ck2018")
2)对持久化的rdd调用对应的checkpoint方法
- rdd1.checkpoint
3)后续还是需要一个action
- rdd1.collect
实例
[root@node01 ~]# spark-shell --master spark://node01:7077
scala> sc.setCheckpointDir("/sparkdata/ck2018")
scala> val rdd1=sc.textFile("/sparkdata/input/word.txt")
//checkpoint方法
scala> rdd1.checkpoint
//后续还是需要一个action
scala> rdd1.collect
scala>
//查看一下
[root@node02 ~]# hdfs dfs -ls /sparkdata/ck2018/421de263-cbcf-4430-8015-6c4021bb8e81/rdd-1
Found 2 items
-rw-r--r-- 3 root supergroup 40 2000-00-00 14:40 /sparkdata/ck2018/421de263-cbcf-4430-8015-6c4021bb8e81/rdd-1/part-00000
-rw-r--r-- 3 root supergroup 12 2000-00-00 14:40 /sparkdata/ck2018/421de263-cbcf-4430-8015-6c4021bb8e81/rdd-1/part-00001
catch/persist/checkpoint区别
简言之:checkpoint会开启一个新的job去执行checkpoint操作,会改变rdd的血统,后期通过血统重新恢复数据,数据写入hdfs,程序退出也存在。
细言之:
cache和persist:都可以把数据进行缓存,后面需要action操作才会触发任务运行。它二者不会改变rdd的血统。它们不会开启新的job去执行cache和persist操作。
程序退出或者手动删除后缓存就会没有。
checkpoint:把数据写入hdfs上,最大程度保证数据安全性。它后面也需要一个action,这时候action会产生一个job,对应的这个job执行完后,又会重新开启一个新的job去执行checkpoint操作。后期它会改变rdd的血统。程序退出缓存还是存在。
(七)spark运行架构
1)构建Spark Application的运行环境(启动SparkContext),SparkContext向资源管理器(可以是Standalone、Mesos、yarn)注册并申请运行Executor资源;
2)资源管理器分配Excutor资源并启动Exexutor,Executor运行情况随着心跳发送到资源管理器上;
3)SparkContext构建成DAG有向无环图,将DAG图分解成Stage,并把Taskset发送给Task Scheduler。
Executor向SparkContext申请Task,Task Scheduler将Task发放给Executor运行,同时ParkContext将应用程序代码发放给Executor。
4)Task在Executor上运行,运行完毕释放所有资源。
Spark运行架构特点
-
每个application获取专属的executor进程,该进程在application期间一直驻留,并以多线程方式运行tasks
-
spark任务与资源管理器无关,只要能够获取executor进程,并能保持相互通信就可以了
-
提交运行SparkContext的Client应该靠近Worker节点(运行Executor的节点),最好在同一个Rack机架里,因为Spark程序运行过程中SparkContext和Executor之间有大量信息交互
-
Task采用了数据本地性和推测执行的优化机制