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()
}
}