我尝试使用hadoop格式化和排序一个非常大的数据集,但它似乎跳过了排序步骤。Map器将avro输入文件转换为json中的几个有趣字段。
void map(AvroWrapper<Datum> wrappedAvroDatum, NullWritable nothing,
OutputCollector<Text, Text> collector, Reporter reporter) {
Datum datum = wrappedAvroDatum.datum();
if (interesting(datum)) {
Long time = changeTimeZone(datum.getTime());
String key = "%02d".format(month(time));
String value = "{\"time\": %d, \"other-stuff\": %s, ...}".format(time, datum.getOtherStuff());
collector.collect(new Text(key), new Text(value));
}
}
reducer假设每个键的值都是按字典顺序排列的(适用于 org.apache.hadoop.io.Text
,对吗?)然后去掉键,这样我就得到一个文本文件,每行一个json对象。
void reduce(Text key, java.util.Iterator<Text> values,
OutputCollector<NullWritable, Text> collector, Reporter reporter) {
while (values.hasNext()) {
collector.collect(NullWritable.get, new Text(values.next()));
}
}
我希望文本文件以一个月为单位进行排序(也就是说,我不希望月份是有序的,但我希望每个月内的时间是有序的)。我得到的是按月份分组但完全未排序的文本文件。显然,hadoop正在将 Text
记录按其键值排序,但不会对其进行排序。
(已知问题:我相信 "time"
在我的json对象中是第一位的,所有记录的位数都完全相同,所以字典顺序是数字顺序。我的数据也是如此。)
当我使用hadoop流媒体(在这个项目中不是一个选项)时,文本行被自动排序——排序可以被配置,但是默认情况下它做了我想要的。在原始hadoop中,排序是否需要以某种方式打开?如果是,怎么做?如果在默认情况下它应该是开的,我可以从哪里开始调试这个问题?
我在cloudera的cdh4hadoop-0.20包的伪分布式模式和amazon的elasticmapreduce(emr)上观察到了这种行为。
1条答案
按热度按时间klr1opcd1#
hadoop排序键,而不是值。这意味着你得到的结果是正确的。hadoop没有跳过排序阶段;它实际上是在整理钥匙。
你可以自己设计
Writable
键入以使用复合键并确保所需的排序类型。另一个问题解释了如何做到这一点。最后,这个问题提供了更多关于hadoop中shuffle&sort阶段如何工作的信息。