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