SparkContext里面的地图

时间:2015-04-24 07:48:49

标签: scala apache-spark

我有大量的文件夹(10.000个文件夹),其中包含.gz文件,并尝试按文件夹执行某些操作,例如:将每个文件分成较小的部分。

为此,我决定:

  1. 获取文件夹路径列表,如Array [String]
  2. 将这个相当大的列表并行化为节点
  3. foldersRDD.foreach(folderName => .... sc.textFile(folderName) ....
  4. 它在本地工作但在集群上导致NullPointerException(我想,每个执行器节点的SparkContext都为null,我们根本不能在节点的函数代码中使用它)。
    我如何以确保 1-folder-per-single-worker 执行模式的方式重做此示例或以其他方式避免/最小化任何繁重的操作,如洗牌?

2 个答案:

答案 0 :(得分:1)

您可以将解决方案与命令wholeTextFiles()完全结合使用。这只是一个技巧,但它可能对你有用。

根据official spark documentation,命令wholeTextFiles()允许您读取包含多个小文本文件的目录,并将每个文件作为filename/content对返回。这与textFile()形成对比,后者将在每个文件中每行返回一条记录。

您可以从原始文件夹路径数组开始创建一组键/值 RDD-s,每个RDD-s代表{{1}中整个文件夹的名称和内容数据格式。

考虑以下开始场景:

filename/content

假设您有一个数组字符串,其中包含每个文件夹的名称

Folder 1 (location > hdfs:\\Folder1)
    - File01 (location > hdfs:\\Folder1\File01) > Hello this is the content of file 01
    - File02 (location > hdfs:\\Folder1\File02) > Hello this is the content of file 02

Folder 2 (location > hdfs:\\Folder1)
    - File03 (location > hdfs:\\Folder2\File03) > Hello this is the content of file 03
    - File04 (location > hdfs:\\Folder2\File04) > Hello this is the content of file 04

下一步是为每个文件夹创建一个RDD。每个RDD将以DirArray[0]: "hdfs:\\Folder1" DirArray[1]: "hdfs:\\Folder2" 格式表示整个文件名列表及其内容。为此,您可以遍历 path 数组并为每个元素调用命令filename/content。它将包含以下内容:

wholeTextFiles()

每个结果RDD看起来如下所示:

For each element in DirArray > wholeTextFiles("hdfs:\\FolderN")

此时,将有两种选择:

a)将每个RDD存储在类似数组的结构中,稍后计算其元素

b)计算每个RDD生成时的元素(在前面中为每个部分)。

重要的是要注意,这种方法仅建议用于一组小文件,主要是因为新创建的RDD-s的每一行都包含它所代表的文件的全部内容。

答案 1 :(得分:0)

在您的示例中,foreach中的代码被序列化并转移给工作者。你是对的,他们没有sparkContext。

我的建议:使用foldersList而不是RDD,并祈祷您的RDD是在数据所在的同一工作人员上创建的。在理想的情况下,你有小文件(在许多节点上没有被hdfs划分)并且每个工作者都有足够的内存 - 就没有改组。在实际案例中,yarn会降低您的成本 - 这是他的工作,而不是您的工作。

P.S。可能会有一些技巧和其他更有经验的人可以更好地回答你。我只是建议信任hadoop magic引擎盖,并花时间在算法的实际实现上。祝你好运!