Hadoop:使用MapReduce流式传输文件,我可以控制输出部分的顺序吗?

时间:2015-10-14 12:21:48

标签: java hadoop

我正在尝试使用BZip2在HDFS上压缩文件。使用MapReduce流式传输这样做似乎是一种很好的方法,根据以下帖子的答案:

Hadoop compress file in HDFS

该帖子的相关代码示例为:

    hadoop jar contrib/streaming/hadoop-streaming-1.0.3.jar \
            -Dmapred.reduce.tasks=0 \
            -Dmapred.output.compress=true \
            -Dmapred.compress.map.output=true \
            -Dmapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec \
            -input filename \
            -output /filename \
            -mapper /bin/cat \
            -inputformat org.apache.hadoop.mapred.TextInputFormat \
            -outputformat org.apache.hadoop.mapred.TextOutputFormat
hadoop fs -cat /path/part* | hadoop fs -put - /path/compressed.gz

实际上,我已经完成了与上面相同的工作,而不是BZip2,使用Java Hadoop Streaming API,并使用ToolRunner从非集群机器调用集群上的流作业。

这种方法的重要特征是:

  1. 因为这是一个输入格式为文本的流作业,所以只从映射任务输出值,而不是键,即文件行的内容而不是字节偏移量。

  2. 这是一项仅限地图的工作。我相信这意味着在地图阶段结束时不会进行排序,这会使其有效。

  3. 将单独的拉链部件连接在一起以生成单个压缩文件。

  4. 尝试过这种方法后,我发现它看起来效率很高,但后来发现无法保证part *文件在连接在一起之前的顺序正确。即当我解压缩文件时,这些块本身总是内部正确,但有时候顺序错误。

    我一直在考虑的可能解决方案基本上分为两类 - 或者是否引入减速器。

    如果引入Reducer,那么以下帖子似乎相关:

    MapReduce job output sort order

    问题不是相同的要求,但是对所有部分*文件进行全局排序的想法似乎是相关的,并且可以通过以其他方式覆盖默认分区程序来完成。但是,我不认为这符合我的目的,因为如果我有减速器,那么地图阶段将对数据进行排序(按字母顺序对行数据进行排序,因为密钥不是按照上面的第1点编写的),我不想发生。即使我可以阻止排序,但感觉使用reducer并不是解决这个问题的方法。

    所以我只想找到一种方法来使用零减速器来完成这项工作。我真正想要的是一种以某种方式跟踪/标记/排序输入分割的方法,这样当部分*文件来自MapReduce时,我知道如何对它们进行重新排序,以便在它解压缩时,该文件与原始文件相同。但是我怀疑MapReduce不是以这种方式工作的 - 即作为用户我无法控制分割本身,并且地图作业彼此独立运行并且可以按任何顺序完成。

    如果有人对如何解决这个问题有任何想法,我一直希望收到你的来信,谢谢。

0 个答案:

没有答案