如何使用Spark API处理大型目录树?

时间:2015-11-19 10:32:19

标签: java scala hadoop apache-spark

我是一名新的Spark用户,我正在尝试处理位于HDFS文件系统上的大型XML文件集。一个"开发"大约有150k文件,总共大约28GB。一台机器的集群(实际上是一台虚拟机)。

文件被组织成HDFS中的目录结构,使得在单个父目录下有大约一百个子目录。每个孩子"目录包含几百到几千个XML文件之间的任何内容。

我的任务是解析每个XML文件,使用XPath表达式提取一些值,并将结果保存到HBase。我试图用Apache Spark做到这一点,我没有太多运气。我的问题似乎是Spark API和RDD工作方式的结合。在这一点上,分享一些伪代码以表达我想要做的事情可能是谨慎的:

RDD[String] filePaths = getAllFilePaths()
RDD[Map<String,String>] parsedFiles = filePaths.map((filePath) => {
    // Load the file denoted by filePath
    // Parse the file and apply XPath expressions
})
// After calling map() above, I should have an RDD[Map<String,String>] where
// the map is keyed by a "label" for an xpath expression, and the
// corresponding value is the result of the expression applied to the file 

因此,将我写给HBase的部分折扣一下,让我们重点关注上述内容。我无法从RDD map()调用中加载文件。

我尝试了很多不同的方法,但都失败了:

  1. 使用callSparkContext.textFile("/my/path")加载文件失败,因为SparkContext不可序列化
  2. 使用Hadoop API中的callFileSystem.open(path),其中FileSystem在RDD之外实例化失败,因为FileSystem不可序列化
  3. 使用来自Hadoop API的FileSystem.open(path)调用,FileSystem在中实例化,RDD失败,因为程序用尽了文件句柄。
  4. 其他方法包括尝试使用SparkContext.wholeTextFiles("/my/path/*"),因此我不必在map()调用中执行文件加载,因为程序内存不足而失败。这可能是因为它急切地加载文件。

    有没有人在自己的工作中尝试过类似的东西,如果有的话,你使用了什么方法?

1 个答案:

答案 0 :(得分:-1)

尝试使用通配符来读取整个目录。 val errorCount = sc.textFile("hdfs://some-directory/*")

实际上,spark可以读取整个hfs目录,引用spark documentation

  

所有Spark的基于文件的输入方法,包括textFile,都支持   在目录,压缩文件和通配符上运行。对于   例如,您可以使用textFile("/my/directory"),   textFile("/my/directory/*.txt")textFile("/my/directory/*.gz")