我正在尝试用多个输入文件在java中使用hadoop。目前我有两个文件,一个大的要处理,一个小的用作索引。
我的问题是,我需要保持整个索引文件未被丢弃,同时将大文件分发给每个Map器。hadoopapi是否提供了任何方法来实现这种功能?
如果你没有正确地表达自己,这里有一个链接到一个图片,代表我正在努力实现:图片
更新:
按照santiago提供的说明,我现在可以将amazon s3中的一个文件(或者至少是uri)插入分布式缓存,如下所示:
job.addCacheFile(new Path("s3://myBucket/input/index.txt").toUri());
但是,当Map程序试图读取它时,会出现“找不到文件”异常,这对我来说很奇怪。我已经检查了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
}
我使用的是amazon的emr、s3和hadoop的2.4.0版本。
3条答案
按热度按时间gblwokeq1#
如上所述,将索引文件添加到分布式缓存中,然后在Map器中访问该文件。在幕后。hadoop框架将确保在执行任何任务之前将索引文件发送到所有任务跟踪器,并可供您处理。在这种情况下,数据只传输一次,并且将可用于与您的作业相关的所有任务。
但是,不要在Map程序代码中将索引文件添加到分布式缓存中,而是让驱动程序代码实现toolrunner接口并重写run方法。这提供了在提交作业时通过命令提示符将索引文件传递到分布式缓存的灵活性
如果使用的是toolrunner,则可以在运行作业时直接从命令行将文件添加到分布式缓存中。无需先将文件复制到hdfs。使用-files选项添加文件
您可以按以下方式访问mapper或reducer代码中的文件:
0h4hbjxa2#
以下是帮助我解决问题的方法。
因为我将amazon的emr与s3一起使用,所以我需要稍微修改一下语法,如下站点所述。
必须添加系统从缓存中读取文件时要使用的名称,如下所示:
job.addcachefile(新uri(“s3://mybucket/input/index.txt”+“#index.txt”);
这样,程序就知道引入缓存的文件名为just index.txt。我还需要更改语法以从缓存中读取文件。不必读取存储在分布式缓存中的整个路径,只需使用文件名,如下所示:
jucafojl3#
您可以将索引文件推送到分布式缓存,并在执行Map程序之前将其复制到节点。
看这条线。