spark之累加器和广播变量
spark的三大数据结构
RDD:分布式数据集
广播变量:分布式只读共享变量
累加器:分布式只写共享变量
1.累加器
默认累加器
例子:对一个list中的所有值进行相加
首先上图中红色部分框出来的代码,看上去逻辑没有什么大问题,但是输出的结果sum=0。这是因为,sum在Driver中被定义,在不同的executor中计算,每个executor得到值既不能彼此相加,也不能传回Driver输出,所以导致Driver中sum的值一直没有变过。
这时候就可以采用累加器,因为Driver和各个executor都需要使用这个数据,所以在这里定义一个只写共享变量是合适的。累加器解决的问题就是数据原本不能从executor传回driver的问题。
自定义累加器
例子:取出含有"u"的字符串,累加
- 继承AccumulatorV2
- 重写方法
class WordAccumulator extends 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("u")){
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上下文对象
val sc = new SparkContext(config)
val value = sc.makeRDD(List("us","tomoon","oneus","you","loc"))
val accumulator = new WordAccumulator
//需要注册一下
sc.register(accumulator)
value.foreach {
case i => {
accumulator.add(i)
}
}
println(accumulator.value)
sc.stop()
2.广播变量
使用的时候只要把原本的数据通过broadcast()转化成广播变量,使用的时候通过broadcast.value使用即可。