[英]Hadoop Map Whole File in Java
我正在尝试在具有多个输入文件的Java中使用Hadoop 。 目前,我有两个文件,一个要处理的大文件和一个作为索引的较小文件。
我的问题是,在将大文件分发到每个映射器时,我需要保持整个索引文件不分裂 。 Hadoop API提供了什么方法来制作这种东西?
如果未正确表达自己的想法,以下是一个图片链接,该链接代表我要实现的目标: 图片
更新:
按照圣地亚哥提供的说明,我现在能够将来自Amazon S3的文件(至少是URI)插入分布式缓存中,如下所示:
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
}
我正在使用Amazon的EMR , S3和Hadoop的 2.4.0版本。
如上所述,将索引文件添加到“分布式缓存”,然后在映射器中访问该文件。 在幕后。 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");
您可以将索引文件推送到分布式缓存,然后在执行映射器之前将其复制到节点。
请参阅此SO线程 。
这是帮助我解决问题的方法。
由于我在S3上使用了Amazon的EMR ,因此我需要对语法进行一些更改,如以下站点所述 。
有必要添加系统打算用来读取缓存中的文件名 ,如下所示:
job.addCacheFile(new 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
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.