SPARK三大数据结构

Spark 三大数据结构

	Spark 有三大数据结构 RDD、广播变量、累加器。
	rdd 是弹性分布式数据集。
	广播变量: 分布式只读共享变量。
	累加器: 分布式只写共享变量。

Spark 累加器

默认累加器

package com.ypl.bigdata.spark

import java.util

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

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

      val config: SparkConf = new SparkConf().setMaster("local[*]").setAppName("rdd_serialble")

      // 创建 SPARK 上下文对象
      val sc = new SparkContext(config)
      val dataRDD: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4), 2)
      var sum:Int = 0
      // 使用累加器来共享变量,来累加数据
      // 创建累加器对象
      val accumulator: LongAccumulator = sc.longAccumulator
    
      // 创建自定义累加器
      // 注册累加器
      //dataRDD.foreach(i=> sum=sum+i)
      val result = dataRDD.foreach {
        case i => {
          accumulator.add(i)
        }
      }
      println("sum = " + accumulator.value)
      sc.stop()
    }
}

自定义累加器

package com.ypl.bigdata.spark

import java.util

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

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

      val config: SparkConf = new SparkConf().setMaster("local[*]").setAppName("rdd_serialble")

      // 创建 SPARK 上下文对象
      val sc = new SparkContext(config)

      val dataRDD: RDD[String] = sc.makeRDD(List("hadoop","hive","hbase","spark","ypl"), 2)

      var sum:Int = 0

      // 使用累加器来共享变量,来累加数据

      // 创建累加器对象

      val accumulator: WordAccumulator = new WordAccumulator
      //注册累加器
      sc.register(accumulator)

      dataRDD.foreach {
        case words => {
          accumulator.add(words)
        }

      }
      println("sum = " + accumulator.value)


      sc.stop()
    }
}

//声明累加器
//1.继承 AccumulatorV2
//2.实现抽象方法
//3.声明累加器
//4、注册累加器
class WordAccumulator() extends org.apache.spark.util.AccumulatorV2[String, util.ArrayList[String]] {

  val list = new util.ArrayList[String]()

  // 当前累加器是否为初始化状态
  override def isZero: Boolean ={
    list.isEmpty
  }
  // 复制累加器
  override def copy(): AccumulatorV2[String, util.ArrayList[String]] = {
    new WordAccumulator()
  }

  //重置累加器
  override def reset(): Unit = {
      list.clear()
  }
  // 向累加器中增加数据
  override def add(v: String): Unit = {
    if (v.contains("h")){
      list.add(v)
    }
  }
  // 将另外的数据合并到一起了
  override def merge(other: AccumulatorV2[String, util.ArrayList[String]]): Unit = {
    list.addAll(other.value)
  }
  override def value: util.ArrayList[String] = list
}

spark 广播变量

广播变量(调优策略)
广播变量用来高效分发较大的对象。向所有工作节点发送一个较大的只读值,以供一个或多个Spark操作使用。比如,如果你的应用需要向所有节点发送一个较大的只读查询表,甚至是机器学习算法中的一个很大的特征向量,广播变量用起来都很顺手。 在多个并行操作中使用同一个变量,但是 Spark会为每个任务分别发送。

scala> val broadcastVar = sc.broadcast(Array(1, 2, 3))

broadcastVar: org.apache.spark.broadcast.Broadcast[Array[Int]] = Broadcast(35)

scala> broadcastVar.value

res33: Array[Int] = Array(1, 2, 3)

使用广播变量的过程如下:

(1)通过对一个类型T的对象调用SparkContext.broadcast创建出一个Broadcast[T]对象,任何可序列化的类型都可以这么实现。

(2)通过value属性访问该对象的值(在。

(3)变量只会被发到各个节点一次,应作为只读值处理(修改这个值不会影响到别的节点)。

package com.ypl.bigdata.spark

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

object Spark_Broadcast {
    def main(args: Array[String]): Unit = {
      val config: SparkConf = new SparkConf().setMaster("local[*]").setAppName("rdd_serialble")
      // 创建 SPARK 上下文对象
      val sc = new SparkContext(config)
      val rdd = sc.makeRDD(List((1,"a"),(2,"b"),(3,"c")))
      val rdd2 = sc.makeRDD(List((1,1),(2,2),(3,3)))
//
//      val joinRDD = rdd.join(rdd2)
//      /*
//      *
//      * (2,(b,2))
//        (1,(a,1))
//        (3,(c,3))
//      *
//      * */
//      joinRDD.foreach(println)
//
      // 使用广播变量可以减少数据的传输  避免shuffle 过程,笛卡尔积现象
     val list = List((1,1),(2,2),(3,3))
     val broadcast: Broadcast[List[(Int, Int)]] = sc.broadcast(list)
     val resultRDD: RDD[(Int, (String, Any))] = rdd.map {
        case (key, value) => {
          var v2: Any = null
          for (t <- broadcast.value) {
            if (key == t._1) {
              v2 = t._2
            }
          }
          (key, (value, v2))
        }
      }
      resultRDD.foreach(println)
      sc.stop()
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章