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数据库