SPark学习笔记:03-SPark的RDD详解

文章目录

  • 概述
  • RDD的创建
    • 基于现有的集合创建RDD
    • 基于文件创建RDD
  • 深入理解RDD
    • 1、怎么理解RDD的分布式
    • 2、怎么理解RDD之间有一系列依赖关系
    • 3、怎么理解RDD的弹性(容错性)
    • 4、怎么理解RDD提供了最佳的计算位置

概述

Resilient Distributed Datasets(RDDs),中文名称是弹性分布式数据集。Spark的所有操作围绕着RDDs展开。它是一组可容错的、可并行操作的数据的集合。我们可以通过两种方式来创建一个RDDs:

  • 通过一个现有的集合创建
  • 应用外部存储系统中的数据集,如本地文件系统,HDFS,HBASE等。

RDD的创建

基于现有的集合创建RDD

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
object RddTest {
  def main(args: Array[String]): Unit = {

    //1.创建sparkConf
    val sparkConf:SparkConf = new SparkConf()
    sparkConf.setAppName("RddTest")
    sparkConf.setMaster("local")

    //2.创建SparkContext
    val sparkContext:SparkContext = new SparkContext(sparkConf)
    
    //3.创建RDD
    var array:Array[String] = Array("one","two","three","four","five","six"," ")
    val numRdds:RDD[String] = sparkContext.parallelize[String](array,2)
    
    //4.遍历打印RDD的元素
    numRdds.foreach(println)
    
    //5.关闭sparkContext
    sparkContext.close()
 }
}

基于文件创建RDD

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}
case class SensorReading(id:String,timestamp:BigInt,temperature:Double)
object RddTest {

  def myMapFunction(value:String):(String,Int)={
    return (value,1)
  }

  def main(args: Array[String]): Unit = {

    //1.创建sparkConf
    val sparkConf:SparkConf = new SparkConf()
    sparkConf.setAppName("RddTest")
    sparkConf.setMaster("local")

    //2.创建SparkContext
    val sparkContext:SparkContext = new SparkContext(sparkConf)

    val inpath:String = "D:\\javaworkspace\\BigData\\Spark\\SparkApp\\src\\main\\resources\\sensor.txt"
    val rdd1:RDD[String] = sparkContext.textFile(inpath,2)

    //过滤掉空的数据
    val rdd2:RDD[String] = srcdata.filter(data=>{data.nonEmpty})

    //将rdd2转换为Sensor
    val rdd3:RDD[SensorReading] = rdd2.map(data=>{
      val arr = data.split(",")
      SensorReading(arr(0),arr(1).toLong,arr(2).toDouble)
    })

    rdd3.foreach(println)

    //4.关闭sparkContext
    sparkContext.stop()
  }

}

深入理解RDD

RDD(Resilient Distributed Dataset),弹性分布式数据集。它具有以下5大特性:

  • RDD是由一系列的partition组成的。
  • 函数是作用在每一个partition上的。
  • RDD之间有一系列的依赖关系(如示例)
  • 分区器是作用在K,V格式的RDD上。
  • RDD提供一系列最佳的计算位置。

要理解以上几点,我们先来看一张RDD的数据图:
image

1、怎么理解RDD的分布式

在上面的示例中结合上图所示,我们基于文件使用sparkContext.TextFile()创建了一个RDD1,我们知道,在实际的运用场景中,我们的数据文件一般都是存放在HDFS文件系统中的。
我们知道,HDFS上的文件会被切割成一个个的Block(默认是128M),分布在不同的DataNode节点上。而RDD则是由一系列的Partition组成,默认情况下,一个Partition对应文件的一个Block(我们在创建RDD时可以通过参数指定Partition的个数,如上面代码中所示),如上图所示,因此RDD也是分布式的(不同的Partition分布在不同的节点上)。

2、怎么理解RDD之间有一系列依赖关系

由上图所示,我们可以很清晰的看到,RDD3依赖RDD2、RDD2依赖RDD1.所以说RDD之间是有依赖关系的(组成一个有向无环图DAG),另外很重要的一点,RDD实际是不存储整个block数据,或者说它不存储数据,只是封装了一个对数据的计算过程,数据实际是存放在HDFS的block上的。如RDD2.map对RDD2做算子运算时,会一步步向上追溯,读取block的一行,然后进行RDD1.filter()算子运算,计算完毕后将结果丢给RDD2.map的方法进行处理,然后输出结果。如图中不同RDD之间的数据传递是在内存中进行的,不涉及到文件IO。

3、怎么理解RDD的弹性(容错性)

  • RDD实际是与HDFS文件的Block对应的,HDFS的Block一般都会设有副本分布在不同的节点上,假如某一个RDD在处理时发生异常,Spark可以在副本所在的节点重新开始任务
  • 即使没有副本,因为RDD之间是有依赖关系的,如果当前RDD数据丢失,我们可以基于上一个RDD重新计算出当前RDD
  • RDD的partition数量、大小没有限制,可以通过参数动态修改,体现了RDD的弹性

4、怎么理解RDD提供了最佳的计算位置

我们知道,在大数据处理中,资源的最大消耗在于IO处理,所以原则上尽可能少的发生IO操作。而RDD是由partition组成,partition与文件的block对应。所以spark会在block所在的节点创建task来对数据进行处理,即数据本地化计算原则。

你可能感兴趣的:(Spark,大数据,spark,学习,大数据)