2012-06-13 3 views
6

Я пишу работу MapReduce, которая может закончиться огромным количеством значений в редукторе. Меня беспокоят, что все эти значения загружаются в память сразу.Значения Hadoop Reducer в памяти?

Выполняет ли базовую реализацию значений Iterable<VALUEIN> values значения в памяти по мере необходимости? Hadoop: Окончательное руководство, похоже, предполагает, что это так, но не дает «окончательного» ответа.

Выход редуктора будет намного более массивным, чем ввод значений, но я считаю, что выход записывается на диск по мере необходимости.

ответ

12

Вы правильно читаете книгу. Редуктор не сохраняет все значения в памяти. Вместо этого при переходе через список значений Iterable каждый экземпляр объекта повторно используется, поэтому он сохраняет только один экземпляр в заданное время.

Например, в следующем коде objs ArrayList будет иметь ожидаемый размер после цикла, но каждый элемент будет тем же b/c, что экземпляр Text val повторно используется на каждой итерации.

public static class ReducerExample extends Reducer<Text, Text, Text, Text> { 
public void reduce(Text key, Iterable<Text> values, Context context) { 
    ArrayList<Text> objs = new ArrayList<Text>(); 
      for (Text val : values){ 
        objs.add(val); 
      } 
    } 
} 

(Если по какой-то причине вы действительно хотели предпринять дальнейшие действия на каждом валу, вы должны сделать глубокую копию, а затем сохранить его.)

Конечно, даже одно значение может быть больше, чем память , В этом случае разработчику рекомендуется предпринять шаги для обработки данных в предыдущем Mapper, чтобы значение было не таким большим.

ОБНОВЛЕНИЕ: См. Страницы 199-200 от Hadoop. Окончательное руководство. 2-е издание.

This code snippet makes it clear that the same key and value objects are used on each 
invocation of the map() method -- only their contents are changed (by the reader's 
next() method). This can be a surprise to users, who might expect keys and vales to be 
immutable. This causes prolems when a reference to a key or value object is retained 
outside the map() method, as its value can change without warning. If you need to do 
this, make a copy of the object you want to hold on to. For example, for a Text object, 
you can use its copy constructor: new Text(value). 

The situation is similar with reducers. In this case, the value object in the reducer's 
iterator are reused, so you need to copy any that you need to retain between calls to 
the iterator. 
+0

Я смущен вашим ответом. Сначала вы говорите: «редуктор не сохраняет все значения в памяти», что подразумевает, что значение Iterable загружается по мере необходимости. Позже вы говорите: «даже один список значений значений может быть больше, чем память», подразумевая, что список значений сначала загружается в память. Не могли бы вы прояснить? – Zach

+0

Отредактировано для уточнения. Я просто имел в виду, что даже одно значение может быть большим. Это маловероятно. «Редуктор не сохраняет все значения в памяти» - это истинное утверждение. Имеет ли это смысл? –

+0

Да. Спасибо за уточнение. У вас есть ссылка на это, случайно? – Zach

2

Это не совсем в памяти, некоторые из них идет с диска, глядя на код, кажется, что структура разбивает Iterable на сегменты, и загрузить их образуют диск в память 1 по одному.

org.apache.hadoop.mapreduce.task.ReduceContextImpl org.apache.hadoop.mapred.BackupStore

+0

Не могли бы вы объяснить, как это решит проблему? –

0

Как цитирует других пользователей, все данные были не загружены в память. Посмотрите на некоторые параметры mapred-site.xml от ссылки на документацию Apache.

mapreduce.reduce.merge.inmem.threshold 

Значение по умолчанию: 1000. Это пороговое значение, с точки зрения количества файлов для процесса объединения в памяти.

mapreduce.reduce.shuffle.merge.percent 

Значение по умолчанию - 0,66. Порог использования, при котором будет инициироваться слияние в памяти, выраженное в процентах от общей памяти, выделенной для хранения выходов карты памяти в памяти, как определено mapreduce.reduce.shuffle.input.buffer.percent.

mapreduce.reduce.shuffle.input.buffer.percent 

Значение по умолчанию - 0,70. Процентная доля памяти, которая должна быть выделена из максимального размера кучи, чтобы хранить выходы карты во время тасования.

mapreduce.reduce.input.buffer.percent 

Значение по умолчанию равно 0. Процентная доля памяти по отношению к максимальному размеру кучи - для сохранения выходов карты во время уменьшения. Когда перетасовка завершается, любые оставшиеся выходы карты в памяти должны потреблять меньше этого порога до начала сокращения.

mapreduce.reduce.shuffle.memory.limit.percent 

Значение по умолчанию: 0.25. Максимальный процент ограничения в памяти, которое может потреблять один случайный случай,

Смежные вопросы