Spark 总结之RDD(二)

Spark 总结之RDD(二)

1. 背景

  1. Spark作为分布式数据处理引擎,在企业实践中大量应用.对比Mapreduce既有性能上的优势,也有开发编程上的便捷性优势.
  2. Spark针对数据处理,对编程接口做了更高层级的抽象和封装,API使用起来更加方便.其中RDD DataSet DataFrame DStream等都是抽象出来的数据处理对象.
  3. RDD使用时会屏蔽掉具体细节,操作起来就跟操作Scala的集合对象一样便捷.

2. RDD常见算子和方法

2.1 RDD创建 查看方法

  • RDD创建
package com.doit.rddInfo

import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

class RDDInfo1{
   

}

object RDDInfo1 {
   
  def main(args: Array[String]): Unit = {
   
    val conf = new SparkConf()
    conf.setAppName(classOf[RDDInfo1].toString )
    conf.setMaster("spark://linux101:7077")

    val sc = new SparkContext(conf)

    val array: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8)

    // 创建rdd
    val rdd1: RDD[Int] = sc.parallelize(array)
    val rdd2: RDD[Int] = sc.makeRDD(array)

    // 指定数据分区,分区数决定了并行task数
    val rdd3: RDD[Int] = sc.parallelize(array, 4)
    val rdd4: RDD[Int] = sc.makeRDD(array, 6)


    println(rdd1.collect().toBuffer)
    println("======")

    println(rdd2.collect().toBuffer)
    println("======")

    println(rdd3.collect().toBuffer)
    println("======")

    println(rdd4.collect().toBuffer)
    println("======")

    sc.stop()
  }
}

  • 查看分区数量
rdd1.partitions.length

2.2 RDD常见Transformation算子

1. map算子
  • 最核心最关键的算子之一,顾名思义,主要是做转换数据使用,由此可以延伸出多种用途.
val conf = new SparkConf()
    conf.setAppName(classOf[RDDInfo1].toString )
    conf.setMaster("spark://linux101:7077")

    val sc = new SparkContext(conf)

    val array: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8)

    // 创建rdd
    val rdd1: RDD[Int] = sc.parallelize(array)

    // 数据转换
    val mapedValue: RDD[Int] = rdd1.map(ele => ele * 10)
  • map方法的源码
/**
   * Return a new RDD by applying a function to all elements of this RDD.
   */
  def map[U: ClassTag](f: T => U): RDD[U] = withScope {
   
    val cleanF = sc.clean(f)
    new MapPartitionsRDD[U, T](this, (_, _, iter) => iter.map(cleanF))
  }
private[spark] def clean[F <: AnyRef](f: F, checkSerializable: Boolean = true): F = {
   
    ClosureCleaner.clean(f, checkSerializable)
    f
  }

上面可以看出,
map方法参数就是一个函数, 泛型T=>U
map方法返回是一个RDD
map方法内部实现是,先调用sc.clean(f),这是因为RDD内部包含的是数据来源和数据处理逻辑,最终是要转换为Task对象序列化之后分发给各个executor执行的,所以需要检查是否包含不可序列化的内容
接下来就是创建了一个MapPartitionsRDD对象,这个对象接收2个参数,一个是this,就是当前的RDD,一个是函数
(_, _, iter) => iter.map(cleanF),从函数构成来看,大致最后一个参数是一个迭代器,通过迭代器,让每个迭代器中元素应用一次传进来的函数

private[spark] class MapPartitionsRDD[U: ClassTag, T: ClassTag](
    var prev: RDD[T],
    f: (TaskContext, Int, Iterator[T]) => Iterator[U],  // (TaskContext, partition index, iterator)
    preservesPartitioning: Boolean = false,
    isFromBarrier: Boolean = false,
    isOrderSensitive: Boolean = false)
  extends RDD[U](prev) 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值