Spark一个非常重要的特性就是共享变量。 默认情况下,如果在一个算子的函数中使用到了某个外部的变量,那么这个变量的值会被拷贝到每个task中。此时每个task只能操作自己的那份变量副本。如果多个task想要共享某个变量,那么这种方式是做不到的。
Spark为此提供了两种共享变量
- 一种是Broadcast Variable(广播变量),
- 另一种是Accumulator(累加变量)。
广播变量
广播变量限定只读 (缓存在每台worker中的cache),可应用在 任务与任务之间共享,不用再不同任务之间传递变量。Broadcast Variable会将使用到的变量,仅仅为每个节点拷贝一份,更大的用处是优化性能,减少网络传输以及内存消耗。
object AccumulatorVariable {
def main(args: Array[String]) {
val conf = new SparkConf()
.setAppName("AccumulatorVariable")
.setMaster("local")
val sc = new SparkContext(conf)
val sum = sc.accumulator(0)
val numberArray = Array(1, 2, 3, 4, 5)
val numbers = sc.parallelize(numberArray, 1)
numbers.foreach { num => sum += num }
println(sum)
}
累加器
累加器限定只写 (通过关联操作进行"加"操作的变量),可应用在任务与驱动器之间共享,Accumulator则可以让多个task共同操作一份变量,主要可以进行累加操作。例如调试时,对Job的执行过程中事件进行计数。
例子:计算file文件中空行
import org.apache.spark.{SparkContext, SparkConf}
/**
* Created by chh on 2016/5/22.
*/
object Counter {
def main(args :Array[String]): Unit = {
//创建一个scala版本的SparkContext
val conf = new SparkConf().setAppName("Counter").setMaster("local")
val sc = new SparkContext(conf)
val file=sc.textFile("file.txt")
val blankLines =sc.accumulator(0)//创建Accumulator[Int]并初始化为0
val callSigns =file.flatMap(line => {
if(line == ""){
blankLines += 1 //累加器加一
}
line.split(" ")
})
callSigns.saveAsTextFile("output.txt")
println(blankLines.value)
}
}