1、RDD任务划分
RDD任务切分分为:Application、Job、Stage和Task
1)Application:初始化一个SparkContext即生成一个Application
2)Job:一个Action算子就会生成一个Job
3)Stage:根据RDD之间的依赖关系的不同将Job划分成不同的Stage,遇到一个宽依赖则划分一个Stage。
4)Task:Stage是一个TaskSet,将Stage划分的结果发送到不同的Executor执行即为一个Task。
注意:Application->Job->Stage-> Task每一层都是1对n的关系。
2、 RDD缓存(每次取用RDD不需要重复计算,还是之前的RDD对象)
RDD通过persist方法或cache方法可以将前面的计算结果缓存,默认情况下 persist() 会把数据以序列化的形式缓存在 JVM 的堆空间中。
缓存有可能丢失,或者存储于内存的数据由于内存不足而被删除
RDD的缓存容错机制保证了即使缓存丢失也能保证计算的正确执行。通过基于RDD的一系列转换,丢失的数据会被重算,由于RDD的各个Partition是相对独立的,因此只需要计算丢失的部分即可,并不需要重算全部Partition。
3、RDD CheckPoint
Spark中对于数据的保存除了持久化操作之外,还提供了一种检查点的机制,检查点(本质是通过将RDD写入Disk做检查点)是为了通过lineage做容错的辅助,lineage过长会造成容错成本过高,这样就不如在中间阶段做检查点容错,如果之后有节点出现问题而丢失分区,从做检查点的RDD开始重做Lineage,就会减少开销。检查点通过将数据写入到HDFS文件系统实现了RDD的检查点功能。
4、键值对RDD数据分区器
Spark目前支持Hash分区和Range分区,用户也可以自定义分区
注意:
(1)只有Key-Value类型的RDD才有分区器的,非Key-Value类型的RDD分区器的值是None
(2)每个RDD的分区ID范围:0~numPartitions-1,决定这个值是属于那个分区的。
Hash分区
HashPartitioner分区的原理:对于给定的key,计算其hashCode,并除以分区的个数取余,如果余数小于0,则用余数+分区的个数(否则加0),最后返回的值就是这个key所属的分区ID。
Ranger分区
HashPartitioner分区弊端:可能导致每个分区中数据量的不均匀,极端情况下会导致某些分区拥有RDD的全部数据。
自定义分区
需要继承 org.apache.spark.Partitioner 类并实现下面三个方法。 numPartitions: Int,getPartition(key: Any): Int:,equals():Java
使用自定义的 Partitioner 是很容易的:只要把它传给 partitionBy() 方法即可
5、数据的存储与保存
Spark的数据读取及数据保存可以从两个维度来作区分:文件格式以及文件系统。
文件格式分为:Text文件、Json文件、Csv文件、Sequence文件以及Object文件;
文件系统分为:本地文件系统、HDFS、HBASE以及数据库。
文件类数据读取与保存
1) Text文件
数据读取:textFile(String)
数据保存: saveAsTextFile(String)
2)Json文件(应用中多是采用SparkSQL处理JSON文件。)
如果JSON文件中每一行就是一个JSON记录,那么可以通过将JSON文件当做文本文件来读取
3)Sequence文件
SequenceFile文件是Hadoop用来存储二进制形式的key-value对而设计的一种平面文件(Flat File)。Spark 有专门用来读取 SequenceFile 的接口。在 SparkContext 中,可以调用 sequenceFile[ keyClass, valueClass](path)。
注意:SequenceFile文件只针对PairRDD
4)对象文件
对象文件是将对象序列化后保存的文件,采用Java的序列化机制。
文件系统类数据读取与保存
1) HDFS
2) MySQL
3)HBase数据库