Spark开发

文章介绍了Spark中如何通过集合、本地文件和HDFS文件创建RDD,重点讨论了parallelize和textFile方法。同时,详细阐述了Spark的Transformation和Action操作,如map、filter、reduceByKey等,强调了Transformation的lazy特性,并通过代码示例展示了这些操作的使用。
摘要由CSDN通过智能技术生成

第一步:创建RDD

Spark提供三种创建RDD方式:** 集合、本地文件、HDFS文件**

  1. 使用程序中的集合创建RDD,主要用于进行测试,可以在实际部署到集群运行之前,自己使用集合构造一些测试数据,来测试后面的spark应用程序的流程。
  2. 使用本地文件创建RDD,主要用于临时性地处理一些存储了大量数据的文件
  3. 使用HDFS文件创建RDD,是最常用的生产环境的处理方式,主要可以针对HDFS上存储的数据,进行离线批处理操作。
使用集合创建RDD

如果要通过集合来创建RDD,需要针对程序中的集合,调用SparkContext的parallelize()方法。Spark会将集合中的数据拷贝到集群上,形成一个分布式的数据集合,也就是一个RDD。相当于,集合中的部分数据会到一个节点上,而另一部分数据会到其它节点上。然后就可以用并行的方式来操作这个分布式数据集合了

	object CreateRddByArrayscala {
 		def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
    conf.setAppName("CreateRddByArrayscala")
      .setMaster("local")
    val sc = new SparkContext(conf)
    //创建集合 driver中执行
    val arr = Array(1,2,3,4,5)
    //基于集合创建RDD
    val rdd =sc.parallelize(arr)
    //对集合数据求和
    val sum =rdd.reduce(_ + _)
    //这行代码再driver中执行
    println(sum)

** 注意**
val arr = Array(1,2,3,4,5)还有println(sum)代码是在driver进程中执行的,这些代码不会并行执行parallelize还有reduce之类的操作是在worker节点中执行的

使用本地文件和HDFS文件创建RDD

通过SparkContext的textFile()方法,可以针对本地文件或HDFS文件创建RDD,RDD中的每个元素就是文件中的一行文本内容。textFile()方法支持针对目录、压缩文件以及通配符创建RDD

/**
 * 通过文件创建RDD
 */
object CreateRddByFilescala {
  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
    conf.setAppName("CreateRddByArrayscala")
      .setMaster("local")

    val sc = new SparkContext(conf)
    var path = "D:\\hello.txt"
    //path = hdfs://bigdata01:9000/test/hello.txt
    var rdd =sc.textFile(path,minPartitions = 2)

    //获取每一行数据的长度,计算文件内数据的总长度
    val length = rdd.map(_.length).reduce(_+_)
    println(length);
    sc.stop() 
  }
}

** Spark中对RDD的操作**
Spark对RDD的操作可以整体分为两类:Transformation和Action

Transformation可以翻译为转换,表示是针对RDD中数据的转换操作,主要会针对已有的RDD创建一个新的RDD:常见的有map、flatMap、filter等等.
Action可以翻译为执行,表示是触发任务执行的操作,主要对RDD进行最后的操作,比如遍历、reduce、保存到文件等,并且还可以把结果返回给Driver程序.
不管是Transformation里面的操作还是Action里面的操作,我们一般会把它们称之为算子
其中Transformation算子有一个特性:** lazy **
lazy特性在这里指的是,如果一个spark任务中只定义了transformation算子,那么即使你执行这个任务,任务中的算子也不会执行.
只有当transformation之后,接着执行了一个action操作,那么所有的transformation才会执行。
Spark通过lazy这种特性,来进行底层的spark任务执行的优化,避免产生过多中间结果。
Action的特性:执行Action操作才会触发一个Spark 任务的运行,从而触发这个Action之前所有的Transformation的执行

算子 介绍
map       将RDD中的每个元素进行处理,一进一出
filter    对RDD中每个元素进行判断,返回true则保留
flatMap   与map类似,但是每个元素都可以返回一个或多个新元素
groupByKey 根据key进行分组,每个key对应一个Iterable<value>
reduceByKey 对每个相同key对应的value进行reduce操作
sortByKey  对每个相同key对应的value进行排序操作(全局排序)
join     对两个包含<key,value>对的RDD进行join操作
distinct 对RDD中的元素进行全局去重

Transformation操作开发实战

  1. map:对集合中每个元素乘以2
  2. filter:过滤出集合中的偶数
  3. flatMap:将行拆分为单词
  4. groupByKey:对每个大区的主播进行分组
  5. reduceByKey:统计每个大区的主播数量
  6. sortByKey:对主播的音浪收入排序
  7. join:打印每个主播的大区信息和音浪收入
  8. distinct:统计当天开播的大区信息

scala代码如下:

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

   val sc=  getSparkContext
    groupByKeyOp(sc)
    
  }
  //flatMap:将行拆分为单词
  def flatMapOp(sc: SparkContext): Unit = {
    val dataRdd = sc.parallelize(Array(" good good study","day day up"))
    dataRdd.flatMap(_.split(" ")).foreach(println(_))
  }
 //groupbyKey 对每个大区主播进行分组
  def groupByKeyOp(sc: SparkContext): Unit = {
    val dataRdd =sc.parallelize(Array((150001,"us"),(1500002,"CN"),(150003,"CN"),(1500004,"IN")))
    //需要使用map对tuple中的数据位置进行互换,因为需要把大区作为key进行分组操作
    dataRdd.map(tup=>(tup._2,tup._1)).groupByKey().foreach(tup=>{
      //获取大区
      val area=tup._1
      println(area+":")
      //获取同一个大区对应的所有用户id
      val it = tup._2
      for(uid <- it){
        println(uid+" ")
      }
      println()
    })
  }
    //filter:过滤出集合中的偶数
  def filterOp(sc: SparkContext): Unit = {
    val dataRdd = sc.parallelize(Array(1,2,3,4,5))
    dataRdd.filter(_ %2 ==0).foreach(println(_))
  }
//map:对集合中每个元素乘以2
  def mapOp(sc: SparkContext): Unit = {
   val dataRdd =  sc.parallelize(Array(1,2,3,4,5))
    dataRdd.map(_ * 2).foreach(println(_))
  }
  private def getSparkContext = {
    val conf = new SparkConf()
    conf.setAppName("CreateRddByArrayscala")
      .setMaster("local")
    new SparkContext(conf)

  }
}

常用Action介绍

算子 介绍
reduce   将RDD中的所有元素进行聚合操作
collect  将RDD中所有元素获取到本地客户端(Driver)
count    获取RDD中元素总数
take(n)  获取RDD中前n个元素
saveAsTextFile 将RDD中元素保存到文件中,对每个元素调用toString
countByKey     对每个key对应的值进行count计数
foreach        遍历RDD中的每个元素

scala代码:

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

    val sc =getSparkContext
    //reduce聚合计算
    //reduceOp(sc)
    //collect:获取元素集合
    //colletOp(sc)
    // count:获取元素总数
    //countOp(sc)
    //saveAsTextFile:保存文件
    //saveAsTextFileOp(sc)
    //countByKey:统计相同的key出现多少次
    //countByKeyOp(sc)
    //foreach:迭代遍历元素
    foreachOp(sc)
    sc.stop()
  }
  //foreach:迭代遍历元素
  def foreachOp(sc: SparkContext): Unit = {
    val dataRdd = sc.parallelize(Array(1,2,3,4,5))
    dataRdd.foreach(println(_))
  }
 //countByKey:统计相同的key出现多少次
  def countByKeyOp(sc: SparkContext): Unit = {
    val dataRdd = sc.parallelize(Array(("A",1001),("B",1002),("A",1003),("C",1004)))
    val res = dataRdd.countByKey()
    for((k,v) <- res){
      println(k+","+v)
    }
  }
 //saveAsTextFile:保存文件
  def saveAsTextFileOp(sc: SparkContext): Unit = {
    val dataRdd = sc.parallelize(Array(1,2,3,4,5))
    dataRdd.saveAsTextFile("hdfs://bigdata01:9000/out001")
  }
// count:获取元素总数
  def countOp(sc: SparkContext): Unit = {
    val dataRdd = sc.parallelize(Array(1,2,3,4,5))
    val res = dataRdd.count()
    println(res)
  }
 //collect:获取元素集合
  def colletOp(sc: SparkContext): Unit = {
    val dataRdd = sc.parallelize(Array(1,2,3,4,5))
    //collect 返回的是一个Array数组
    val res = dataRdd.collect()
    for(item <- res){
      println(item)
    }
  }
//reduce聚合计算
  def reduceOp(sc: SparkContext): Unit = {
    val dataRdd = sc.parallelize(Array(1,2,3,4,5))
    val num = dataRdd.reduce(_ + _)
    println(num)
  }

  private def getSparkContext = {
    val conf = new SparkConf()
    conf.setAppName("CreateRddByArrayscala")
      .setMaster("local")
    new SparkContext(conf)
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值