入门篇 - RDD 介绍

概念

RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是 Spark 中最基本的数据
处理模型。代码中是一个抽象类,它代表一个弹性的、不可变、可分区、里面的元素可并行 计算的集合。

  1. 弹性
    • 存储的弹性:内存与磁盘的自动切换
    • 容错的弹性:数据丢失可以自动恢复;
    • 计算的弹性:计算出错重试机制;
    • 分片的弹性:可根据需要重新分片。
  2. 分布式 :数据存储在大数据集群不同节点上
  3. 数据集:RDD封装了计算逻辑,并不保存数据
  4. 数据抽象:RDD是一个抽象类,需要子类具体实现
  5. 不可变:RDD封装了计算逻辑,是不可以改变的,想要改变,只能产生新的RDD,在
    新的 RDD 里面封装计算逻辑
  6. 可分区、并行计算

基础编程

RDD 的创建

从集合(内存)中创建 RDD

从集合中创建 RDD,Spark 主要提供了两个方法:parallelizemakeRDD

val sparkConf =
   new SparkConf().setMaster("local[*]").setAppName("spark")
val sparkContext = new SparkContext(sparkConf)
val rdd1 = sparkContext.parallelize(
   List(1,2,3,4)
)
val rdd2 = sparkContext.makeRDD(
   List(1,2,3,4)
)
rdd1.collect().foreach(println)
rdd2.collect().foreach(println)
sparkContext.stop()

其实从底层实现来说,makeRDD 方法其实就是 parallelize 方法

def makeRDD[T: ClassTag](
   seq: Seq[T],
   numSlices: Int = defaultParallelism): RDD[T] = withScope {
  parallelize(seq, numSlices)
}

从外部存储(文件)创建 RDD

由外部存储系统的数据集创建 RDD 包括:本地的文件系统,所有 Hadoop 支持的数据集, 比如 HDFS、HBase 等。

val sparkConf =
new SparkConf().setMaster("local[*]").setAppName("spark")
val sparkContext = new SparkContext(sparkConf)
val fileRDD: RDD[String] = sparkContext.textFile("input")
fileRDD.collect().foreach(println)
sparkContext.stop()

从其他 RDD 创建

主要是通过一个 RDD 运算完后,再产生新的 RDD。

直接创建 RDD(new)

使用 new 的方式直接构造 RDD

RDD 并行度与分区

默认情况下,Spark 可以将一个作业切分多个任务后,发送给 Executor 节点并行计算,而能 够并行计算的任务数量我们称之为并行度。这个数量可以在构建 RDD 时指定。记住,这里 的并行执行的任务数量,并不是指的切分任务的数量,不要混淆了

val sparkConf =
   new SparkConf().setMaster("local[*]").setAppName("spark")
val sparkContext = new SparkContext(sparkConf)
val dataRDD: RDD[Int] = sparkContext.makeRDD(List(1, 2, 3, 4), 4)
val fileRDD: RDD[String] = sparkContext.textFile("input", 2)
fileRDD.collect().foreach(println)
sparkContext.stop()

读取内存数据时,数据可以按照并行度的设定进行数据的分区操作,数据分区规则的 Spark 核心源码如下:

def positions(length: Long, numSlices: Int): Iterator[(Int, Int)] = {
  (0 until numSlices).iterator.map { i =>
   val start = ((i * length) / numSlices).toInt
   val end = (((i + 1) * length) / numSlices).toInt
   (start, end)
}

读取文件数据时,数据是按照Hadoop文件读取的规则进行切片分区,而切片规则和数 据读取的规则有些差异,具体 Spark 核心源码如下

public InputSplit[] getSplits(JobConf job, int numSplits)
   throws IOException {
long totalSize = 0; // compute total size
for (FileStatus file: files) { // check we have valid files
     if (file.isDirectory()) {
       throw new IOException("Not a file: "+ file.getPath());
     }
     totalSize += file.getLen();
}
long goalSize = totalSize / (numSplits == 0 ? 1 : numSplits);
long minSize = Math.max(job.getLong(org.apache.hadoop.mapreduce.lib.input.
   FileInputFormat.SPLIT_MINSIZE, 1), minSplitSize);
  ...
  for (FileStatus file: files) {
     ...
  if (isSplitable(fs, path)) {
       long blockSize = file.getBlockSize();
       long splitSize = computeSplitSize(goalSize, minSize, blockSize);
...
}
protected long computeSplitSize(long goalSize, long minSize,
                               long blockSize) {
  return Math.max(minSize, Math.min(goalSize, blockSize));
}

你可能感兴趣的:(入门篇 - RDD 介绍)