广播变量用来高效分发较大的对象,是一种调优策略
广播变量是每个Executor的内存中,只传一个变量副本,而不是对每一个task都传输一次大变量。也就是向所有工作节点发送一个较大的只读值,以供一个或多个Spark操作使用。
普通RDD操作
object JoinTest {
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("test")
val sc = new SparkContext(conf)
val rdd1 = sc.makeRDD(List((1, "a"), (2, "b"), (3, "c")))
val rdd2 = sc.makeRDD(List((1, 11), (2, 22), (3, 33)))
rdd1.join(rdd2).foreach(println)
}
}
结果
(1,(a,11))
(3,(c,33))
(2,(b,22))
上面代码把k-v类型RDD中k相同的value放到元组中,但是join是一种宽依赖,所以会产生shuffle,并且join会有笛卡尔积,所以效率很低
使用广播变量进行优化
//使用广播变量优化
object BroadCast {
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("test")
val sc = new SparkContext(conf)
val rdd1 = sc.makeRDD(List((1, "a"), (2, "b"), (3, "c")))
val rdd2 = sc.makeRDD(List((1, 11), (2, 22), (3, 33), (3, 222)))
//使用广播变量
val broadcast: Broadcast[Array[(Int, Int)]] = sc.broadcast(rdd2.collect())
//自定义一个累加器
val myaccumulator = new Myaccumulator2()
//使自定义累加器生效
sc.register(myaccumulator)
//这里用map,这时窄依赖,可以使整个过程没有shuffle,提高性能
val value: RDD[(Int, util.ArrayList[Any])] = rdd1.map {
case (k, v) => {
for (t <- broadcast.value) {
if (k == t._1) {
//将key对应的value放到累计器中
myaccumulator.add(t._2)
}
}
//把自己的value放到累加器
myaccumulator.add(v)
//返回结果
(k, myaccumulator.value)
}
}
//打印
value.foreach(println)
}
}
上面需要用到的自定义的累加器Myaccumulator2
package spark.accumulator
import java.util
import org.apache.spark.util.AccumulatorV2
class Myaccumulator2 extends AccumulatorV2[Any, util.ArrayList[Any]] {
val arrlist = new util.ArrayList[Any]()
//是否是空
override def isZero: Boolean = arrlist.isEmpty
//拷贝出一份Myaccumulator
override def copy(): AccumulatorV2[Any, util.ArrayList[Any]] = new Myaccumulator2()
//初始化aeelist数组,使其为空
override def reset(): Unit = arrlist.clear()
//往arrlist增加数据
override def add(v: Any): Unit =
//把值大于5的放到arrlist
arrlist.add(v)
//把各个分区的arrlist合并到一起
override def merge(other: AccumulatorV2[Any, util.ArrayList[Any]]): Unit =
arrlist.addAll(other.value)
//把合并好的arrlist发送给val值
override def value: util.ArrayList[Any] = arrlist
}