我正尝试在java中使用Hadoop来处理多个输入文件。目前我有两个文件,一个大文件要处理,一个小文件作为索引。
我的问题是,当大文件分发给每个映射器时,我需要维护完整的索引文件。Hadoop提供了任何方法来制造这样的东西吗?
如果没有正确地表达自己,这里有一个链接,它代表了我正在尝试实现的目标:图片
更新:
按照圣地亚哥提供的说明,我现在能够将文件(至少是URI )从亚马逊的S3插入到分布式缓存中,如下所示:
job.addCacheFile(new Path("s3://myBucket/input/index.txt").toUri());
然而,当映射器试图读取它时,会出现一个“未找到的文件”异常,这在我看来是很奇怪的。我检查了S3的位置,一切似乎都很好。我使用了其他S3位置来介绍输入和输出文件。
错误(注意s3:之后的单个斜杠)
FileNotFoundException: s3:/myBucket/input/index.txt (No such file or directory)
下面是从分布式缓存读取文件的代码:
URI[] cacheFile = output.getCacheFiles();
BufferedReader br = new BufferedReader(new FileReader(cacheFile[0].toString()));
while ((line = br.readLine()) != null) {
//Do stuff
}
我使用的是亚马逊的EMR、S3和Hadoop的2.4.0版本。
发布于 2014-06-24 07:41:10
以下是帮助我解决问题的方法。
由于我在S3中使用的是亚马逊的EMR,所以我需要修改语法,如下面的站点所述。
有必要添加系统用于从缓存中读取文件的名称,如下所示:
Job.addCacheFile(新URI("s3://myBucket/input/index.txt“+ "#index.txt"));
这样,程序就知道引入缓存的文件名为“index.txt”。我还需要更改语法,以便从缓存中读取文件。不必读取存储在分布式缓存中的整个路径,只需使用文件名,如下所示:
URI[] cacheFile = output.getCacheFiles();
BufferedReader br = new BufferedReader(new FileReader(#the filename#));
while ((line = br.readLine()) != null) {
//Do stuff
}
发布于 2014-06-20 12:11:17
如前所述,将索引文件添加到分布式缓存中,然后在映射器中访问该文件。在幕后。Hadoop框架将确保在执行任何任务之前将索引文件发送到所有任务跟踪器,并可供您处理。在这种情况下,数据只传输一次,并可用于与您的工作相关的所有任务。
但是,不要在映射程序代码中将索引文件添加到分布式缓存中,而是让驱动程序代码实现ToolRunner接口并覆盖run方法。这提供了在提交作业时通过命令提示符将索引文件传递给分布式缓存的灵活性。
如果使用ToolRunner,则可以在运行作业时从命令行直接将文件添加到分布式缓存中。不需要先将文件复制到HDFS。使用-files选项添加文件
hadoop jar yourjarname.jar YourDriverClassName -files cachefile1, cachefile2, cachefile3, ...
可以访问Mapper或Reducer代码中的文件,如下所示:
File f1 = new File("cachefile1");
File f2 = new File("cachefile2");
File f3 = new File("cachefile3");
发布于 2014-06-20 11:40:22
您可以将索引文件推送到分布式缓存,并在执行映射程序之前将其复制到节点。
看这个所以线。
https://stackoverflow.com/questions/24325101
复制相似问题