Java 使用Spark API如何处理大型目录树?
我是一个新的Spark用户,我正在尝试处理HDFS文件系统上的一大组XML文件。在一台由1台机器(实际上是一台VM)组成的“开发”集群上,大约有150k个文件,总计约28GB 这些文件在HDFS中被组织成一个目录结构,这样在一个父目录下大约有100个子目录。每个“子”目录包含几百到几千个XML文件之间的任何内容 我的任务是解析每个XML文件,使用XPath表达式提取一些值,并将结果保存到HBase。我正试图用ApacheSpark实现这一点,但我运气不太好。我的问题似乎是Spark API和RDD工作方式的结合。在这一点上,分享一些伪代码来表达我的意图可能是明智的:Java 使用Spark API如何处理大型目录树?,java,scala,hadoop,apache-spark,Java,Scala,Hadoop,Apache Spark,我是一个新的Spark用户,我正在尝试处理HDFS文件系统上的一大组XML文件。在一台由1台机器(实际上是一台VM)组成的“开发”集群上,大约有150k个文件,总计约28GB 这些文件在HDFS中被组织成一个目录结构,这样在一个父目录下大约有100个子目录。每个“子”目录包含几百到几千个XML文件之间的任何内容 我的任务是解析每个XML文件,使用XPath表达式提取一些值,并将结果保存到HBase。我正试图用ApacheSpark实现这一点,但我运气不太好。我的问题似乎是Spark API和RD
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
RDD[String]filepath=getAllFilePath()
RDD[Map]parsedFiles=filePath.Map((filePath)=>{
//加载由filePath表示的文件
//解析文件并应用XPath表达式
})
//在调用上面的map()之后,我应该有一个RDD[map],其中
//映射由xpath表达式的“标签”键控,而
//相应的值是应用于文件的表达式的结果
因此,暂且不谈我给HBase写的那部分内容,让我们把重点放在上面。我无法从RDD map()调用中加载文件
我尝试了许多不同的方法,但都失败了:
SparkContext.textFile(“/my/path”)
加载文件失败,因为SparkContext
不可序列化FileSystem.open(path)
,其中在RDD外部实例化文件系统
失败,因为文件系统
不可序列化FileSystem.open(path)
,其中在RDD内部实例化文件系统
,会失败,因为程序没有文件句柄李>
其他方法包括尝试使用SparkContext.wholeTextFiles(“/my/path/*”)
,这样我就不必从map()调用中加载文件,因为程序内存不足而失败。这大概是因为它急切地加载文件
有人在自己的工作中尝试过类似的事情吗?如果是,您使用了什么方法?尝试使用通配符读取整个目录。
val errorCount=sc.textFile(“hdfs://some-directory/*")
实际上,spark可以读取整个hfs目录,引用spark的话
Spark的所有基于文件的输入方法,包括textFile,都支持
在目录、压缩文件和通配符上运行。对于
例如,您可以使用textFile(“/my/directory”)
,
textFile(“/my/directory/*.txt”)
,和textFile(“/my/directory/*.gz”)
我认为
wholeTextFiles
是一条出路。只需添加更多内存。谢谢您的评论。不幸的是,我没有28GB的内存。当我拿到一个更大的文件集,比如说500GB而不是28 GB时,采用这种方法就会崩溃。不,wholeTextFiles
只需要足够的内存来加载最大的文件。如果你有更多的文件,那很好,你不需要更多的内存。(每个执行器线程一次加载一个文件。您还可以限制执行器线程的数量,这样每个线程就有更多内存。)感谢您的回复。我已经考虑过了,但这是大约28GB的数据,超过150000个文件-如果该方法急切地将文件加载到RDD中,那么它将无法放入内存中。您可以根据这些文件的目录将其分为几个批吗?我的意思是,您可以将文件分为5或8个输入RDD,每次一个。顺便说一下,这不是RDDmap()
应该做的。我想我可以,但那必须通过编程来完成。你对map()的评论是什么意思?@Jon你所做的是在RDD之间,而不是在一个RDD内,所以这不是RDD的map()
函数所能做的。sc.textFile
将所有文件读入一个RDD,每个文件行有一个RDD行。您将无法知道每个文件的开始和结束位置。