Scala SparkContext内部地图
我有一个很大的文件夹列表(10.000个文件夹),里面有.gz文件,并尝试在每个文件夹的基础上做一些事情,例如将每个文件拆分为较小的部分 为此,我决定:Scala SparkContext内部地图,scala,apache-spark,Scala,Apache Spark,我有一个很大的文件夹列表(10.000个文件夹),里面有.gz文件,并尝试在每个文件夹的基础上做一些事情,例如将每个文件拆分为较小的部分 为此,我决定: 获取文件夹路径列表作为数组[字符串] 将这个相当大的列表并行化到节点 foldersRDD.foreach(folderName=> .... sc.textFile(folderName) .. 它在本地工作,但在集群上会导致NullPointerException(我猜,SparkContext对于每个执行器节点都是null的,我们根本不能
foldersRDD.foreach(folderName=>
....
sc.textFile(folderName)
..
我如何重做这个例子,以确保1-folder-per-single-worker执行模式,或者以其他方式避免/最小化任何繁重的操作,比如洗牌?在您的例子中,
foreach
中的代码被序列化并传输到worker。没错,它们上面没有sparkContext
我的建议是:使用foldersList
而不是RDD,并祈祷您的RDD是在数据所在的同一个worker上创建的。在理想情况下,您有小文件(在许多节点上不被HDF分割)而且每个员工都有足够的内存-不会有混乱。在实际情况下,这会降低你的成本-这是他的工作,而不是你的
另外,可能会有一些技巧,其他更有经验的人可以更好地回答您。我只是建议您信任hadoop magic under the hood,并将您的时间花在算法的实际实现上。祝您好运!您可以将您的解决方案与命令
wholeTextFiles()结合使用
。这只是一个小把戏,但可能对你有好处
根据,命令wholeTextFiles()
允许您读取包含多个小文本文件的目录,并以filename/content
对返回每个小文本文件。这与textFile()
相反,后者将在每个文件中每行返回一条记录
您可以从文件夹路径的原始数组开始,创建一组键/值RDD-s,每个键/值RDD-s以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
假设您有一个字符串数组,其中包含每个文件夹的名称
DirArray[0]: "hdfs:\\Folder1"
DirArray[1]: "hdfs:\\Folder2"
下一步是为每个文件夹创建一个RDD。每个RDD将以filename/content
格式表示整个文件名列表及其内容。为此,您可以遍历路径数组并调用命令wholeTextFiles()
用于每个元素。它包括以下内容:
For each element in DirArray > wholeTextFiles("hdfs:\\FolderN")
每个结果RDD如下所示:
firstFolderRDD (key/value):
- "hdfs:\\Folder1\File01" > "Hello this is the content of file 01
- "hdfs:\\Folder1\File02" > "Hello this is the content of file 02
在这一点上,有两种选择:
a)将每个RDD存储在类似数组的结构中,然后计算其元素
b)在生成每个RDD时计算它们的元素(在前一章中为每个零件)
需要注意的是,这种方法只推荐用于一组小文件,主要是因为新创建的RDD-s的每一行都包含它所表示的文件的全部内容