Scala中SparkContext.sequenceFile(…).foreach的作用域问题

Scala中SparkContext.sequenceFile(…).foreach的作用域问题,scala,apache-spark,Scala,Apache Spark,我的目标是处理通过调用org.apache.spark.rdd.rdd[.].saveAsObjectFile(…)生成的一系列SequenceFile文件夹。我的文件夹结构与此类似: \MyRootDirectory \Batch0001 _SUCCESS part-00000 part-00001 ... part-nnnnn \Batch0002 _SUCCESS part-00000 part-000

我的目标是处理通过调用
org.apache.spark.rdd.rdd[.].saveAsObjectFile(…)
生成的一系列
SequenceFile
文件夹。我的文件夹结构与此类似:

\MyRootDirectory
  \Batch0001
     _SUCCESS
     part-00000
     part-00001
     ...
     part-nnnnn
  \Batch0002
     _SUCCESS
     part-00000
     part-00001
     ...
     part-nnnnn
  ...
  \Batchnnnn
     _SUCCESS
     part-00000
     part-00001
     ...
     part-nnnnn
我需要提取一些持久化的数据,但是我的收集-无论我使用的是
ListBuffer
mutable.Map
,还是任何其他可变类型,都会丢失范围,并且在
sequenceFile(…)的每次迭代中都会出现新的内容。foreach

下面的概念验证生成了一系列“处理目录…”,后面是“1:1”,重复且从不增加,正如我所期望的那样
counter
intList.size

private def proofconcept(rootDirectoryName:String)={
val intList=ListBuffer[Int]()
变量计数器:Int=0
val config=new SparkConf().setAppName(“本地”).setMaster(“本地[1]”)
新文件(rootDirectoryName).listFiles().map(u.toString).foreach{folderName=>
println(s“正在处理目录$folderName…”)
val sc=新的SparkContext(配置)
sc.setLogLevel(“警告”)
sc.sequenceFile(folderName,classOf[NullWritable],classOf[BytesWritable]).foreach(f=>{
计数器+=1
intList+=计数器
println(s“$counter:${intList.size}”)
})
sc.停止()
}
}
输出:

"C:\Program Files\Java\jdk1.8.0_111\bin\java" ...
Processing directory C:\MyRootDirectory\Batch0001...
17/05/24 09:30:25.228 WARN  [main] org.apache.hadoop.util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
[Stage 0:>                                                         (0 + 0) / 57]  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
Processing directory C:\MyRootDirectory\Batch0002...
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
Processing directory C:\MyRootDirectory\Batch0003...
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1
  1 : 1

foreach
中的函数在spark worker JVM中运行,而不是在定义变量的客户机JVM中运行。该worker在本地获取该变量的副本,对其进行递增并打印。我猜你是在本地测试这个?如果您在生产、分布式spark环境中运行此程序,您甚至看不到这些打印的输出

更一般地说,几乎所有传递到RDD方法中的函数都可能是远程执行的,并且不会对任何局部变量或任何东西进行可变访问。它将获得它们的一个基本不变的快照


如果要将数据从spark的分布式存储移回客户端,请使用RDD的
collect
方法。使用
sc.parallelize
可实现相反的操作。但请注意,这两种情况通常很少发生,因为它们不会同时发生。

当火花消失时,您看到了吗?