Spark编程指南之八:共享变量、广播变量、累加器

从Spark官网闭包说起

Spark官网Understanding closures(闭包)部分指出,Spark的一个难点在于理解变量和方法的范围和生命周期。

//使用foreach()计算
var counter = 0
var rdd = sc.parallelize(data)

// Wrong: Don't do this!!
rdd.foreach(x => counter += x)

println("Counter value: " + counter)

以上代码将不会正确计算出counter值。Spark会将counter的副本发送到每个executor上,对counter副本的修改不会改变Driver端的counter,counter的值仍然是0。
在这种计数或求和的场景可以使用累加器(Accumulator),下面将详细说明。
参考:http://spark.apache.org/docs/latest/rdd-programming-guide.html#understanding-closures-

共享变量

Spark计算传递的函数是在远程节点上执行的,函数中使用的是变量的副本。这些变量被复制到每台机器上,变量的更新不会返回到Driver端。

示例图

Spark程序计算的时候,函数是分布到每一个节点去执行,所有的变量副本会传给节点计算,但是计算完成后,变量的更新不会返回到driver端。如下图:

发送i
发送i
i
i
i
i
Driver端 Var i=0
Executor端1
Executor端2
Task1 i的副本
Task2 i的副本
Task3 i的副本
Task4 i的副本

代码示例:

val rdd = sc. textFile("README.md")  //下文中rdd默认使用此值,README.md为Spark源码中的文档
val count = rdd.count()
var i = 0
val mapRDD = rdd.map(line => {
  i = i + 1
  (line,line.size) 
})
println("i:" + i)
println("count:" + count)

i:0
count:103
对于跨集群跨任务的变量共享,Spark提供了两种方式:广播变量和累加器。

广播变量(针对只读变量)Broadcast Variables

核心:将只读变量缓存在每个worker节点上。
一:每个节点只要传输一次给Executor,可以给多个Task使用。
二:节点上的变量副本并不都来自与Driver,而是采用了高效广播算法(TorrentBroadcast)降低通信成本。

广播变量有什么作用?

用作Join时的调优map-side join
Join操作 ——》 Shuffle操作 ——》 性能问题
如果Join两边的RDD,有一个RDD的数量较小,可以将小的RDD数据广播出去,将Join转化为map-side join
注意事项: RDD是不能直接广播的。要广播数据,而RDD要遇到Action操作才会执行。
直接广播RDD会提示"Can not directly broadcast RDDs; instead, call collect() and broadcast the result."

val rddData = rdd.collectAsMap()
val rddBC = sc.broadcast(rddData)
val rdd3 = rdd2.mapPartitions(partition => {
	val bc = rddBC.value
	for{
		(key,value) <- partition
		if(rddData.contains(key))
	}yield(key, (bc.get(key).getOrElse(""),value))
})

累加器(只能在Driver端获取)Accumulator

累加器用于Spark任务的计数和求和场景。
累加器只能累加,获取只能在driver端,节点是不知道累加器的值的。
累加器的使用需谨慎,如以下示例:

val acc = sc.longAccumulator("counterAcc")
val mapRDD = rdd.map(line => {
	acc.add(1)
	(line, line.size)
})
val count = mapRDD.count()
val count2 = mapRDD.count()
println("acc.value)

mapRDD.count()两次Action会导致累加器的值翻倍。上述情况使用缓存可以防止acc.value的值翻倍。但实际情况中不推荐使用累加器。

  1. 执行多个action会出错。
  2. 虽然可以缓存,但是缓存可能被清除。
  3. 累加器仅用于程序调试。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值