Spark RDD基本理论和常用算子

一、Spark RDD概述

1、RDD概念

  • 简单的解释
    • RDD是将数据项拆分为多个分区的集合,存储在集群的工作节点上的内存中,并执行正确的操作
  • 复杂的解释
    • RDD是用于数据转换的接口
    • RDD指向了存储在HDFS、Cassandra、HBase等、或缓存(内存、内存+磁盘、仅磁盘等),或在故障或缓存收回时重新计算其他RDD分区中的数据
  • RDD是弹性分布式数据集(Resilient Distributed Datasets)
    • 分布式数据集
      • RDD是只读的、分区记录的集合,每个分区分布在集群的不同节点上
      • RDD并不存储真正的数据,只是对数据和操作的描述
    • 弹性
      • RDD默认存放在内存中,当内存不足,Spark自动将RDD写入磁盘
    • 容错性
      • 根据数据血统,可以自动从节点失败中恢复分区

2、RDD和DAG

  • 两者是Spark提供的核心抽象
  • DAG(有向无环图)反映了RDD之间的依赖关系在这里插入图片描述

3、RDD的特性和流程

  • 特性
    • 一系列的分区(分片)信息,每个任务处理一个分区
    • 每个分区上都有compute函数,计算该分区中的数据
    • RDD之间有一系列的依赖
    • 分区函数决定数据(key-value)分配至哪个分区
    • 最佳位置列表,将计算任务分派到其所在处理数据块的存储位置
  • 流程如下图
    - RDD创建

4、RDD分区

  • 分区是RDD被拆分并发送到节点的不同块之一
    • 我们拥有的分区越多,得到的并行性就越强
    • 每个分区都是被分发到不同Worker Node的候选者
    • 每个分区对应一个Task
      在这里插入图片描述

二、RDD的创建

1、使用集合创建RDD

演示案例:

	val conf: SparkConf = new SparkConf().setMaster("local[2]").setAppName("wordcount")
    val sc: SparkContext = SparkContext.getOrCreate(conf)

    //parallelize和makeRDD基本无区别
    val rdd1: RDD[String] = sc.parallelize(List("hello world","hello java","hello scala"),3)
    val rdd1: RDD[String] = sc.makeRDD(List("hello world","hello java","hello scala"),3)
  • 1、Spark默认会根据集群的情况来设置分区的数量,也可以通过parallelize()第二参数来指定
  • 2、Spark会为每一个分区运行一个任务进行处理

2、通过加载文件产生RDD

演示案例:

    //相对路径
    val lines: RDD[String] = sc.textFile("in/word.txt")
    //绝对路径
    val lines2: RDD[String] = sc.textFile("E:\\Ideal\\sparkdemo1\\in\\word.txt")
    lines2.collect.foreach(println)
    //hdfs路径
    val linesHDFS: RDD[String] = sc.textFile("hdfs://hadoop100:9000/kb09workspace/*.txt")
    linesHDFS.collect.foreach(println)
  • 加载“file://……”时,以local运行仅需一份本地文件,以Spark集群方式运行,应保证每个节点均有该文件的本地副本
  • 支持目录、压缩文件以及通配符
    • 1、Spark默认访问HDFS
    • 2、Spark默认为HDFS文件的每一个数据块创建一个分区,也可以通过textFile()第二个参数指定,但只能比数据块数量多

三、RDD常用算子

1、转换算子

a) 基本概论
  • Transformation(lazy):也称转换操作、转换算子
  • 对于转换操作,RDD的所有转换都不会直接计算结果
    • 仅记录作用于RDD上的操作
    • 当遇到动作算子(Action)时才会进行真正计算在这里插入图片描述
b) 常用的转换算子
val conf = new SparkConf().setMaster("local[*]").setAppName("mapdemo")
val sc = SparkContext.getOrCreate(conf)

map

  • 对RDD中的每个元素都执行一个指定的函数来产生一个新的RDD
  • 任何原RDD中的元素在新RDD中都有且只有一个元素与之对应
  • 输入分区与输出分区一一对应
    println("-----------map---------------")
    val strRdd1 = sc.parallelize(List("4AM","OMG","IFTY","TIANBA","RNG","FAZE"),2)
    strRdd1.map(x=>(x,1)).collect.foreach(println)

filter

  • 对元素进行过滤,对每个元素应用指定函数,返回值为true的元素保留在新的RDD中
    println("----------filter--------------")
    val filterRdd1 = sc.makeRDD(List(1,2,3,4,5,6,7,8,9))
    filterRdd1.filter(_%2==0).collect.foreach(println)

mapValues

  • 原RDD中的Key保持不变,与新的Value一起组成新的RDD中的元素,仅适用于PairRDD
    println("-----------mapValues------------")
    val mapValuesRdd1 = sc.parallelize(List("tiger","dog","lion","cat","panther","eagle"))
    val mapValuesRdd2 = mapValuesRdd1.map(x=>(x.length,x))
    mapValuesRdd2.collect.foreach(println)
    mapValuesRdd2.mapValues(x=>("x"+x+"x")).collect().foreach(println)

	//输出结果:
	//Array((3,dog), (5,tiger), (4,lion), (3,cat), (7,panther), (5,eagle))
	//Array((3,xdogx), (5,xtigerx), (4,xlionx), (3,xcatx), (7,xpantherx), (5,xeaglex))

更多常用转化算子

  • distinct
	println("-----------distinct------------")
	val distinctRdd1 = sc.parallelize(List("aa","bb","aa","bb","cc","dd"))
	val distinctRdd2 = distinctRdd.distinct()
	distinctRdd2.collect.foreach(println)
	//输出结果
	//Array("aa","bb","cc","dd")
  • reduceByKey
    println("---------reduceByKey-----------")
    val reduceByKeyRdd1 = mapValuesRdd2.reduceByKey((a,b)=>a+"-"+b)
    reduceByKeyRdd1.collect().foreach(println)
  • groupByKey
    println("---------groupByKey-----------")
    val groupByKeyRdd = mapValuesRdd2.groupByKey()
    groupByKeyRdd.collect.foreach(println)
  • sortByKey
    println("---------sortByKey-----------")    //默认升序
    val sortByKeyRdd1 = mapValuesRdd2.sortByKey()
    sortByKeyRdd1.collect().foreach(println)
    println("---------sortByKey false-----------")    //false降序
    val sortByKeyRdd2 = mapValuesRdd2.sortByKey(false)
    sortByKeyRdd2.collect().foreach(println)
  • union ++
    println("---------union-----------")
    val unionRdd1 = sc.parallelize(List(1,2,3))
    val unionRdd2 = sc.parallelize(List(1,2,3,4))
    val unionRdd3 = unionRdd1.union(unionRdd2)
    print(unionRdd3.collect.mkString(","))
    println()

    println("---------++-----------")
    val jiajiaRdd1 = unionRdd1 ++ unionRdd2
    print(jiajiaRdd1.collect.mkString(","))
    println()
  • join
    println("---------join-----------")
    val joinRdd1 = sc.parallelize(List("abe","abby","apple")).map(x=>(x,1))
    val joinRdd2 = sc.parallelize(List("apple","beatty","beatrice")).map(x=>(x,1))
    val joinRdd3 = joinRdd1.join(joinRdd2)
    print(joinRdd3.collect.mkString(","))
    println()
    val leftJoinRdd = joinRdd1.leftOuterJoin(joinRdd2)
    print(leftJoinRdd.collect.mkString(","))
    println()
    val rightJoinRdd = joinRdd1.rightOuterJoin(joinRdd2)
    print(rightJoinRdd.collect.mkString(","))
    println()

2、动作算子

a) 基本概论
  • 本质上动作算子通过SparkContext执行提交作业操作,触发RDD DAG(有向无环图)的执行
  • 所有的动作算子都是急迫型(non-lazy),RDD遇到Action就会立即计算
b) 常用动作算子
  • count
    • 返回的是数据集中的元素的个数
	println("--------count----------")
    val rdd=sc.parallelize(List(1,2,3,4,5,6))
    val countRdd: Long = rdd.count
    println(countRdd)
	//输出结果:6
  • collect
    • 以Array返回RDD的所有元素。一般在过滤或者处理足够小的结果的时候使用
    • 应注意到,前面所有转换操作都结合了collect动作算子进行计算输出
    println("--------collect---------")
    val rdd=sc.parallelize(List(1,2,3,4,5,6))
    val collectRdd: Array[Int] = rdd.collect()
    println(collectRdd.mkString(","))
	//输出结果:1,2,3,4,5,6
  • take
    • 返回前n个元素
    println("--------take---------")
    val rdd=sc.parallelize(List(1,2,3,4,5,6))
    val takeRdd: Array[Int] = rdd.take(3)
    println(takeRdd.mkString(","))
	//输出结果:1,2,3
  • first
    • 返回RDD第一个元素
    println("-----first-----")
    val rdd=sc.parallelize(List(1,2,3,4,5,6))
    val firstRdd: Int = rdd.first()
    println(firstRdd)
    //输出结果:1
  • reduce
    • 根据指定函数,对RDD中的元素进行两两计算,返回计算结果
	println("-----reduce-----")
	val rdd1 = sc.parallelize(1 to 100)
    val sum: Int = rdd1.reduce((x, y)=>{println(x,y);x+y})
    println("总和:"+sum)
  • lookup
    • 用于PairRDD,返回K对应的所有V值
    println("-----lookup-----")
    val rdd2=sc.parallelize(List(('a',1), ('a',2), ('b',3), ('c',4)))
    val lookupRdd: Seq[Int] = rdd2.lookup('a')
    println(lookupRdd)
	//输出结果:WrappedArray(1, 2)
  • saveAsTextFile
    • 保存RDD数据至文件系统
	rdd1.saveAsTextFile("in/rdd2.txt")
	rdd1.saveAsTextFile("hdfs://hadoop100:9000/kb09workspace/rdddemodata/rdd1.txt")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值