spark官网中的闭包的解释。。。。

spark官网的地址:http://spark.apache.org/docs/latest/rdd-programming-guide.html#resilient-distributed-datasets-rdds

理解闭包(closure)

Spark的难点之一是在跨集群执行代码时理解变量和方法的范围和生命周期。修改变量范围之外的RDD的操作常常会引起混乱,难以理解。在下面的示例中,我们将查看使用foreach()算子计算+counter的的代码,但是其他操作也可能出现类似的问题。

本地模式VS集群模式

上述代码的行为是未定义的,可能不像预期的那样工作。要执行作业(jobs),Spark将处理RDD操作的每一个job都分解为多个任务(task),每个任务都由executor来执行。在执行之前,Spark计算任务的闭包。闭包就是executor在RDD上执行其计算时必须可见的变量和方法(在本例中foreach())。这个闭包被序列化并且发送到每一个executor上面去。

发送给每个executor的闭包中的counter现在是原来driver端的counter的一个副本,因此,当foreach函数中引用counter时,它不再是driver node上的counter。在driver node的内存中仍然有一个保留原来counter,但是对于executor来说是不可见的。executor只看到序列化闭包中的副本。因此,counter的最终值仍然为零,因为counter上的所有操作都引用了序列化闭包中的值。

在本地模式中,在某些情况下,foreach函数实际上将在与驱动程序相同的JVM中执行,并引用相同的原始计数器,并可能实际更新它.如果你的程序的client和driver端都在windows下面的话,这个结果肯定会更新的。

要确保在这些场景中定义良好的行为,应该使用累加器(Accumulator)。Spark中的累加器专门用于提供一种机制,用于在集群中跨工作节点的执行时安全地更新一个变量。

一般来说,闭包——诸如循环或局部定义的方法之类的结构,不应该用于突变某些全局状态。Spark不定义或保证从闭包外部引用的对象的突变行为。一些这样做的代码可能在本地模式下工作(像上面的foreach()函数),但这只是偶然的,这样的代码在分布式模式下不会像预期的那样运行。如果需要一些全局聚合,则使用累加器。

下面解释一下scala里面的闭包:

scala> (x:Int)=>x+1
res6: Int => Int = $$Lambda$1297/509557834@2aea7775

scala> (x:Int)=>x+a
<console>:13: error: overloaded method value + with alternatives:
  (x: Double)Double <and>
  (x: Float)Float <and>
  (x: Long)Long <and>
  (x: Int)Int <and>
  (x: Char)Int <and>
  (x: Short)Int <and>
  (x: Byte)Int <and>
  (x: String)String
 cannot be applied to ((Int, Int) => Int)
       (x:Int)=>x+a   //这里的a并没有定义,看成是一个free Variable, 而对于x,则是在函数调用的时候会确定类型和值。

//像这种运行时确定变量a型及值的函数称为闭包,a是个自由变量,在运行时其值和类型得以确定

//这是一个由开放(free)到封闭的过程,因此称为闭包

scala> var a =1
a: Int = 1

scala> (x:Int)=>x+a
res8: Int => Int = $$Lambda$1318/658290473@76603c44

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值