rdd的操作和基本逻辑

4 篇文章 0 订阅

cache,persist,checkpoint三者的区别

  1. chche:缓存在内存中,效率高但是不安全,存在数据丢失和内存溢出的风险。而且会在血缘关系中添加依赖
  2. persist:将数据落在磁盘中,可选等级也较为安全。但是在计算完成之后会删除。会在血缘关系中添加依赖
  3. checkpoint:将数据永久保存在路径中(HDFS),可永久保存但是不参与原本的计算会独立计算一次。为了提升效率,一般和cache联合使用。执行过程中会切断血缘关系。重新建立新的血缘关系,等同于改变数据源
    val sc: SparkContext = new SparkContext(conf)
    sc.setCheckpointDir("checkpoint")
    val rdd: RDD[String] = sc.textFile("datas")
    rdd.cache()
    rdd.checkpoint()

分区器(自定义分区)


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


object my_partition {
  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("my_partition")
    val sc = new SparkContext(conf)
    val list: List[(String, String)] = List(("python", "xxxxxxxxxx"),
      ("java", "xxxxxxxxxx"),
      ("scala", "xxxxxxxxxx"),
      ("spark", "xxxxxxxxxx"),
      ("scala", "xxxxxxxxxx")
    )

    val rdd: RDD[(String, String)] = sc.makeRDD(list, 3)
    println("makeRDD")
    rdd.cache()
    //todo 得到去重后的key值
    val keys: List[String] = rdd.map(_._1).distinct().collect().toList
    //todo 根据去重后key的个数从而得到分区数
    val numPartitions: Int = keys.size

    //重新分区,闯入自己的分区器
    val repRDD: RDD[(String, String)] = rdd.partitionBy(new myPartitioner(numPartitions, keys))
    repRDD.saveAsTextFile("output")
    sc.stop()
  }
}

// 自定义分区器继承自Partitioner,重写两个
class myPartitioner(num: Int, list: List[String]) extends Partitioner {
  //分区的数量
  override def numPartitions: Int = num

  // 返回的是数据的额分区索引
  override def getPartition(key: Any): Int = {
    val index: Int = list.indexOf(key)
    index
  }
}

累加器(分布式共享只写变量)

    val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
    // 要定义累加器:因为计算是在executer端,使用需要定义一个累加器来进行计算,只有在driver端计算是无法完成的
    val acc = sc.longAccumulator("acc")
    rdd.foreach(
      num => {
        acc.add(num)
      }
    )
    println(acc.value)

自定义累加器进行wordcount

package com.yan

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

import scala.collection.mutable

object wordCountAcc {

  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("my_partition")
    val sc = new SparkContext(conf)
    val rdd: RDD[String] = sc.makeRDD(List("hello", "spark", "scala", "spark"))
    val wcAcc = new myAcc()
    sc.register(wcAcc, "wc")
    rdd.foreach(
      word =>
        wcAcc.add(word)
    )
    println(wcAcc.value)
    sc.stop()
  }
}

class myAcc extends AccumulatorV2[String, mutable.Map[String, Long]] {
  // 定义一个空map
  private var wcMap = mutable.Map[String, Long]()

  // 判断是都为初始状态
  override def isZero: Boolean = {
    wcMap.isEmpty
  }

  // 复制一个新的累加器
  override def copy(): AccumulatorV2[String, mutable.Map[String, Long]] = {
    new myAcc()
  }

  // 将累加器重置,就是清除
  override def reset(): Unit = {
    wcMap.clear()
  }

  // 获取需要累计的元素
  override def add(v: String): Unit = {
    //判断wcMap里面是否有这个单词
    val newMapCount = wcMap.getOrElse(v, 0L) + 1
    // 这里得到单词和次数
    wcMap.update(v, newMapCount)
  }

  // 合并累加器,other是其他累加器的数据,需要做累加操作
  override def merge(other: AccumulatorV2[String, mutable.Map[String, Long]]): Unit = {
    // 获取其他累加器中的数据,与当前面定义的wcMap进行累加
    other.value.foreach({
      case (word, count) => {
        val newCount: Long = this.wcMap.getOrElse(word, 0L) + count
        //
        this.wcMap.update(word, newCount)
      }
    })
  }

  override def value: mutable.Map[String, Long] = this.wcMap
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值