使用MapReduce API通过Gzip压缩复制HDFS中的文件
我正在用Java编写一个归档程序。将要存档的文件已驻留在HDFS中。我需要能够将文件从HDFS中的一个位置移动到另一个位置,并使用Gzip压缩最终文件。要移动的文件可能相当大,因此使用HDFSAPI来移动和压缩它们可能会非常低效。所以我想我可以在我的代码中写一个mapreduce作业来帮我完成 但是,我找不到任何示例来说明如何使用MapReduceAPI复制这些文件并以gzip格式输出。事实上,我甚至很难找到一个编程示例,说明如何通过mapreduce复制HDFS中的文件 有人能告诉我如何使用MapReduceAPI实现这一点吗 编辑:这是我到目前为止的作业配置代码,它是根据Amar给我的帮助改编的:使用MapReduce API通过Gzip压缩复制HDFS中的文件,map,copy,mapreduce,gzip,reduce,Map,Copy,Mapreduce,Gzip,Reduce,我正在用Java编写一个归档程序。将要存档的文件已驻留在HDFS中。我需要能够将文件从HDFS中的一个位置移动到另一个位置,并使用Gzip压缩最终文件。要移动的文件可能相当大,因此使用HDFSAPI来移动和压缩它们可能会非常低效。所以我想我可以在我的代码中写一个mapreduce作业来帮我完成 但是,我找不到任何示例来说明如何使用MapReduceAPI复制这些文件并以gzip格式输出。事实上,我甚至很难找到一个编程示例,说明如何通过mapreduce复制HDFS中的文件 有人能告诉我如何使用M
conf.setBoolean("mapred.output.compress", true);
conf.set("mapred.output.compression.codec","org.apache.hadoop.io.compress.GzipCodec");
Job job = new Job(conf);
job.setJarByClass(LogArchiver.class);
job.setJobName("ArchiveMover_"+dbname);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
//job.setMapperClass(IdentityMapper.class);
//job.setReducerClass(IdentityReducer.class);
job.setInputFormatClass(NonSplittableTextInputFormat.class);
job.setOutputFormatClass(TextOutputFormat.class);
job.setNumReduceTasks(0);
FileInputFormat.setInputPaths(job, new Path(archiveStaging+"/"+dbname+"/*/*"));
FileOutputFormat.setOutputPath(job, new Path(archiveRoot+"/"+dbname));
job.submit();
下面是LogArchiver类内部的NonSplittableTextInputFormat的类声明
public class NonSplittableTextInputFormat extends TextInputFormat {
public NonSplittableTextInputFormat () {
}
@Override
protected boolean isSplitable(JobContext context, Path file) {
return false;
}
}
您可以使用IdentityMapper和IdentityReducer编写一个。
您可以生成gzip文件作为输出,而不是纯文本文件。在运行中设置以下配置:
为了确保输入和输出中的文件数相同,仅输出文件必须gzip,您必须做两件事:
实现不可分割的TextInputFormat
将reducetasks设置为零。
为了确保每个映射器读取一个文件,您可以按如下方式扩展TextInputFormat:
import org.apache.hadoop.fs.*;
import org.apache.hadoop.mapred.TextInputFormat;
public class NonSplittableTextInputFormat extends TextInputFormat {
@Override
protected boolean isSplitable(FileSystem fs, Path file) {
return false;
}
}
并将上述实现用作:
job.setInputFormatClass(NonSplittableTextInputFormat.class);
要将reduce tasks设置为零,请执行以下操作:
job.setNumReduceTasks(0);
这将为您完成工作,但最后一件事,文件名将不一样!但我也确信这一点,这附近一定有一项工作。不确定这是否有帮助,但您是否研究过Hadoop流媒体?很可能我需要求助于此,但我更喜欢通过MapReduce API来实现。我试试看。再次感谢!你确实让我朝着我的目标走了很长一段路。我现在只有两个问题。1假设我有一个这样的目录结构:top_level/second_level/third_level/file,top_level/second_level/third_level 2/file我如何使输出与输入的目录结构匹配?现在它只是将所有输出文件放在一个目录中。2输出文件的每行前面似乎都有一个数字。它每行递增一次。几乎看起来像一个字符计数。如何确保输出中不包含数字?好的,所以我可以通过实现自己版本的TextOutputFormat类来解决第二个问题,该类排除了键的输出。但仍在试图找出如何使目录结构在输入和输出之间匹配。我认为您可以使用此处解释的MultipleTextOutputFormat来解决此问题:为此,您需要首先在映射中使用以下内容读取输入文件路径:FileSplit context.getInputSplit.getPath.getName,然后使用它相应地设置输出的键,并将完整的有效负载作为值。首先阅读上面的链接,然后你可能会更好地理解它。让我们看看这是否有帮助。
job.setNumReduceTasks(0);