Я только начал изучать Hadoop и все еще экспериментировал и пытался понять вещи, мне действительно интересно узнать об использовании метода collectCollection класса OutputCollector, все примеры, которые я нашел, теперь вызывают этот метод только один раз. Если стоимость вызова этого метода действительно высок (поскольку он записывает вывод в файл)? размышляя о разных сценариях, я попал в ситуацию, когда я нахожу необходимость называть ее более одного раза. подобный мудрый ниже приведенный фрагмент кода
public static class Reduce extends MapReduceBase implements
Reducer<IntWritable, Text, Text, NullWritable> {
public void reduce(IntWritable key, Iterator<Text> values,
OutputCollector<Text, NullWritable> output, Reporter reporter)
throws IOException {
Text outData = null;
while (values.hasNext()) {
outData = new Text();
outData.set(values.next().toString());
output.collect(outData, NullWritable.get());
}
}
}
поскольку объект values
содержит большое количество записей, которые отображает mapper на основе некоторого условия фильтрации, и мне нужно записать эти записи в выходной файл. Или наоборот, я мог бы также использовать приведенный ниже подход.
public static class Reduce extends MapReduceBase implements
Reducer<IntWritable, Text, Text, NullWritable> {
public void reduce(IntWritable key, Iterator<Text> values,
OutputCollector<Text, NullWritable> output, Reporter reporter)
throws IOException {
StringBuilder sb = new StringBuilder();
while (values.hasNext()) {
sb.append(values.next().toString() + "\r\n ");
}
Text outData = new Text();
outData.set(sb.toString());
output.collect(outData, NullWritable.get());
}
}
Однако оба подхода отлично работают на моей настройке в режиме singlelenode для большого набора входных данных до 400 тыс. Записей и values
содержащих около 70 тыс. Записей. Я хочу спросить, какой подход лучше? А также будет ли написанный выше код хорошо вести себя в многоузловом кластере? Любая помощь оценивается. Благодарю.
В конце концов, это сводит к минимуму количество данных (с точки зрения размера в байтах), которые вы пишете.
Оба решения имеют некоторые накладные расходы, в первом примере вы пишете несколько строк, у вас есть постоянные накладные расходы на сериализацию длины каждой строки. В другом решении вы пишете столько же накладных расходов, сколько и разделение строк.
Таким образом, размеры байтов равны, поэтому сбор данных не должен быть значительно медленнее в обоих решениях.
Очень большая часть вашей проблемы - использование памяти, подумайте о очень большой итерации значений, ваш StringBuilder
будет неэффективен из-за операций изменения размера и всей используемой памяти. Метод collect
более умный и разливается на диск, если буфер записи заполнен. С другой стороны, если у вас есть много доступной памяти, и вы хотите записать одну огромную запись в одном go-, это также может быть столь же эффективным, как установка буфера записи одинакового размера.