我正在尝试使用BZip2在HDFS上压缩文件。使用MapReduce流式传输这样做似乎是一种很好的方法,根据以下帖子的答案:
该帖子的相关代码示例为:
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从非集群机器调用集群上的流作业。
这种方法的重要特征是:
因为这是一个输入格式为文本的流作业,所以只从映射任务输出值,而不是键,即文件行的内容而不是字节偏移量。
这是一项仅限地图的工作。我相信这意味着在地图阶段结束时不会进行排序,这会使其有效。
将单独的拉链部件连接在一起以生成单个压缩文件。
尝试过这种方法后,我发现它看起来效率很高,但后来发现无法保证part *文件在连接在一起之前的顺序正确。即当我解压缩文件时,这些块本身总是内部正确,但有时候顺序错误。
我一直在考虑的可能解决方案基本上分为两类 - 或者是否引入减速器。
如果引入Reducer,那么以下帖子似乎相关:
MapReduce job output sort order
问题不是相同的要求,但是对所有部分*文件进行全局排序的想法似乎是相关的,并且可以通过以其他方式覆盖默认分区程序来完成。但是,我不认为这符合我的目的,因为如果我有减速器,那么地图阶段将对数据进行排序(按字母顺序对行数据进行排序,因为密钥不是按照上面的第1点编写的),我不想发生。即使我可以阻止排序,但感觉使用reducer并不是解决这个问题的方法。
所以我只想找到一种方法来使用零减速器来完成这项工作。我真正想要的是一种以某种方式跟踪/标记/排序输入分割的方法,这样当部分*文件来自MapReduce时,我知道如何对它们进行重新排序,以便在它解压缩时,该文件与原始文件相同。但是我怀疑MapReduce不是以这种方式工作的 - 即作为用户我无法控制分割本身,并且地图作业彼此独立运行并且可以按任何顺序完成。
如果有人对如何解决这个问题有任何想法,我一直希望收到你的来信,谢谢。