[Spark基础]--理解Spark闭包

标签: spark 闭包
25人阅读 评论(0) 收藏 举报
分类:

理解Spark的闭包

       对于Spark来说, 最困难的事情之一就是在跨集群执行代码时了解变量和方法的范围和生命周期。RDD 在其范围之外修改变量的操作可能会经常引起混淆。在下面的示例中, 我们将查看使用 foreach () 递增计数器的代码, 但其他操作也可能发生类似的问题。

举例

    考虑下面简单的RDD元素和,它的行为可能会有所不同,这取决于是否在同一个JVM中执行。这方面的一个常见示例是在本地模式下运行星火(--master=local[n])与将星火应用程序部署到集群(例如,通过spark-submit 提交到yarn):

var counter = 0
var rdd = sc.parallelize(data)

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

println("Counter value: " + counter)


看看scala的举例



本地模式与集群模式

     上述代码的行为未定义, 可能无法按预期方式工作。为了执行作业, Spark会将 RDD 操作的处理分解为任务, 每一个都由一个Executor完成。在执行之前,Spark计算任务的闭包。闭包是那些变量和方法必须是可见的执行者在 RDD 上进行计算 (在本例中为 foreach ())。此闭包被序列化并发送到每个executor上。

      发送给每个executor的闭包中的变量现在是副本,因此,当在foreach函数中引用counter 时,它不再是驱动器节点上的计数器。 driver程序节点的内存中仍有一个counter,但executor程序对此不再可见! executor只能看到序列化闭包的副本。 因此,计数器的最终值仍然为零,因为计数器上的所有操作都引用了序列化闭包内的值。

      在本地模式下,在某些情况下,foreach函数实际上将在与driver程序相同的JVM内执行,并且会引用相同的原始counter,并可能实际更新它。

为了确保在这些场景中明确定义的行为,应该使用 Accumulator。 Spark中的 Accumulator专门用于提供一种机制,用于在集群中的工作节点之间执行拆分时安全地更新变量。 本指南的 Accumulator部分更详细地讨论了这些内容。

      一般来说,闭包结构像循环或本地定义的方法,不应该被用来改变一些全局状态。 Spark并没有定义或保证从封闭外引用的对象的突变行为。 这样做的一些代码可以在本地模式下工作,但这只是偶然,并且这种代码在分布式模式下的行为不如预期。 如果需要某些全局聚合,请改用累加器。

打印RDD的元素

      另一个常见的习惯用法是尝试使用rdd.foreach(println)或rdd.map(println)打印RDD的元素。 在单台机器上,这将生成预期的输出并打印所有RDD的元素。 但是,在集群模式下,由executor程序调用的标准输出现在写入执行程序的stdout,而不是driver程序的标准输出,因此driver程序的stdout不会显示这些! 要打印driver程序中的所有元素,可以使用collect()方法首先将RDD带到驱动程序节点:rdd.collect()。foreach(println)。 但是,这可能会导致driver程序内存不足,因为collect()会将整个RDD提取到单台计算机; 如果您只需要打印RDD的几个元素,则更安全的方法是使用take():rdd.take(100).foreach(println)。

总结

1、spark闭包的大致作用就是:函数可以访问函数外面的变量,但是函数内对变量的修改,在函数外是不可见的。

2、scala闭包和spark闭包不一样

3、查看源码:spark对我们所传入的所有闭包函数都做了一次sc.clean操作(查看详情)

参考

  1. http://spark.apache.org/docs/latest/rdd-programming-guide.html#understanding-closures-
  2. https://github.com/highfei2011/SparkDeepDoc



查看评论

移动没有标题的窗体

    我们一般是用鼠标按住窗口的标题栏,然后移动窗口,当窗口没有标题栏时,我们可以用下面的方法来移动窗口: 在 BAS 文件中声明:Declare Function ReleaseCapture L...
  • AttaBoy
  • AttaBoy
  • 2000-12-10 14:07:00
  • 916

[Phoenix基本命令]--phoenix命令汇总

phoenix-4.7.0命令汇总!all Execute the specified SQL against all the current connections !...
  • high2011
  • high2011
  • 2017-05-26 18:03:21
  • 567

15分钟了解Apache Phoenix(HBase的开源SQL引擎)

什么是Phoenix? Phoenix是一个Hbase的开源SQL引擎。你可以使用标准的JDBC API代替hbase客户端API来创建表,插入数据,查询你的HBase数据。 不要在我的程...
  • qq_39532946
  • qq_39532946
  • 2017-08-16 20:25:42
  • 131

Phoenix常见问题解答

Phoenix常见问题解答
  • high2011
  • high2011
  • 2017-06-08 11:30:50
  • 1360

xshell常用快捷键

ctrl+c中断 ctrl+a move the head of command line ctrl+e move the tail of command line ctrl+u 删除光标前面所...
  • a822631129
  • a822631129
  • 2015-10-09 14:17:01
  • 633

HBase+Phoenix平台统计数据出现异常

大体上是统计查询20天的数据总数,数据量大概10多个亿,算起来还行啊,就是报这个错误。在源码中找到报错的地方,大体上是客户端向服务端发送完查询请求,但是服务端还在处理时,客户端已经关掉连接了,各种配置...
  • u014297175
  • u014297175
  • 2015-11-15 17:42:47
  • 925

理解spark闭包

当用户提交了一个用scala语言写的Spark程序,Spark框架会调用哪些组件呢?首先,这个Spark程序就是一个“Application”,程序里面的mian函数就是下图所示的“Driver Pr...
  • liangyihuai
  • liangyihuai
  • 2017-02-24 14:27:09
  • 1459

spark闭包

定义 关于闭包有太多种解释,但基本上都很难用一两句解释清楚,下面这句简短的定义是我见过的最精炼且准确的解释了: A closure is a function that carries an imp...
  • fanyun_01
  • fanyun_01
  • 2016-03-17 12:29:21
  • 1385

理解Spark包中闭包

了解spark难解的地方之一就是明白在集群上运行代码时,明白变量和函数的作用范围和生命周期,在作用域外修改变量的RDD操作很多时候会产生麻烦。接下来展示的例子我们会使用foreach() 来增加变量c...
  • cauchemare_li
  • cauchemare_li
  • 2017-05-09 09:38:45
  • 420

Spark学习——缓存、闭包及共享变量

一、缓存 Spark中也有缓存机制,或者说持久化机制。因为RDD的转化都是惰性的,这就意味着在调用action操作之前Spark是不会计算 的,Spark会在内部记录所要求的执行步骤的全部流程,构...
  • WangQYoho
  • WangQYoho
  • 2017-04-17 16:25:35
  • 1623
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 101万+
    积分: 1万+
    排名: 1106
    博客专栏
    Spark

    文章:46篇

    阅读:55595
    Scala

    文章:48篇

    阅读:68919
    Flink

    文章:1篇

    阅读:659
    Java

    文章:58篇

    阅读:113571
    Kafka

    文章:15篇

    阅读:11859
    CDH

    文章:15篇

    阅读:19589
    最新评论