文章目录
- 一. 累加器:分布式只写变量
- 1.实现原理
- 2. 基础编程
- 2.1系统累加器
- 2.2 自定义累加器
- 二.广播变量:分布式只读变量
- 1.实现原理
- 2.基础编程
学完了Spark core三大数据结构之一的RDD,我们继续来看剩下俩
一. 累加器:分布式只写变量
1.实现原理
累加器用来把 Executor 端变量信息聚合到 Driver 端。在 Driver 程序中定义的变量,在Executor 端的每个 Task 都会得到这个变量的一份新的副本,每个 task 更新这些副本的值后,传回 Driver 端进行 merge。
2. 基础编程
2.1系统累加器
val conf = new SparkConf().setMaster("local[*]").setAppName("test")
val sc = new SparkContext(conf)
val rdd = sc.makeRDD(List(1,2,3,4))
//Spark默认提供了简单数据聚合的累加器
val sumAcc = sc.longAccumulator("sum")
//sc.collectionAccumulator
//sc.doubleAccumulator
rdd.foreach(num=>{
sumAcc.add(num)
})
println(sumAcc.value)
}
少加问题:转换算子中调用累加器,如果没有行动算子,那么不会执行
一般情况下累加器放在行动算子中
2.2 自定义累加器
//继承AccumulatorV2
//定义泛型[in,out],即累加器输入和返回的类型
class MyAccumulator extends AccumulatorV2[String,mutable.Map[String,Long]]
{
private var wcMap = mutable.Map[String,Long]()
//判断是否为初始状态
override def isZero: Boolean = {
wcMap.isEmpty
}
//重置累加器
override def reset(): Unit =
{
wcMap.clear()
}
//获取累加器需要计算的值
override def add(word: String): Unit = {
var newCnt = wcMap.getOrElse(word,0l) + 1
println(wcMap)
wcMap.update(word,newCnt)
}
//获得值
override def value: mutable.Map[String,Long] = {this.wcMap}
override def copy(): AccumulatorV2[String, mutable.Map[String, Long]] = new MyAccumulator
//合并累加器
override def merge(other: AccumulatorV2[String, mutable.Map[String, Long]]): Unit =
{
val map = other.value
map.foreach{
case (word,count)=>
{
val newcount = wcMap.getOrElse(word,0l)+count
map.update(word,newcount)
}
}
}
}
object MyAcc {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local").setAppName("WordCount")
val sparkContext = new SparkContext(conf)
val rdd = sparkContext.makeRDD(List("hello","scala","hello"))
val myacc = new MyAccumulator
//向spark容器注册累加器
sparkContext.register(myacc,"wordCountAcc")
rdd.foreach(word=>
{
myacc.add(word)
})
println(myacc.value)
}
}
二.广播变量:分布式只读变量
1.实现原理
广播变量用来高效分发较大的对象。向所有工作节点发送一个较大的只读值,以供一个或多个 Spark 操作使用。比如,如果你的应用需要向所有节点发送一个较大的只读查询表,广播变量用起来都很顺手。
在spark中,闭包数据以Task为单位发送,这样可能导致一个Excutor中含有大量重复数据。而广播变量放置在一个Executor中共给各个Task共享,这样就节省了内存空间,由于是共享变量,是不可更改的
2.基础编程
//定义广播变量
val bc = sparkContext.broadcast(list)
//获取广播变量
bc.value