2012-06-13 7 views
6

Estoy escribiendo un trabajo de MapReduce que puede terminar con una gran cantidad de valores en el reductor. Me preocupa que todos estos valores se carguen en la memoria a la vez.Hadoop Reducer Values ​​in Memory?

¿La implementación subyacente del Iterable<VALUEIN> values carga valores en la memoria cuando son necesarios? Hadoop: La Guía Definitiva parece sugerir que este es el caso, pero no da una respuesta "definitiva".

La salida del reductor será mucho más masiva que la entrada de valores, pero creo que la salida se escribe en el disco según sea necesario.

Respuesta

12

Estás leyendo el libro correctamente. El reductor no almacena todos los valores en la memoria. En cambio, al recorrer la lista de valores de Iterable, cada instancia de Object se vuelve a utilizar, por lo que solo conserva una instancia en un momento determinado.

Por ejemplo, en el siguiente código, los objs ArrayList tendrán el tamaño esperado después del ciclo, pero cada elemento será el mismo b/c. La instancia de texto del texto se reutilizará en cada iteración.

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); 
      } 
    } 
} 

(Si por alguna razón usted quiso tomar medidas adicionales en cada val, debe hacer una copia profunda y luego lo almacena.)

Por supuesto, incluso un único valor podría ser mayor que la memoria . En este caso, se recomienda al desarrollador que tome medidas para reducir los datos en el Mapper anterior de modo que el valor no sea tan grande.

ACTUALIZACIÓN: Consulte las páginas 199-200 de Hadoop The Definitive Guide 2nd Edition.

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

Estoy confundido por su respuesta. Primero dices, "el reductor no almacena todos los valores en la memoria", lo que implica que el Iterable carga valores según sea necesario. Más tarde, dirá: "incluso una sola instancia de la lista de valores podría ser más grande que la memoria", lo que implica que la lista de valores se carga primero en la memoria. ¿Puedes por favor aclarar? – Zach

+0

Editado para aclarar. Solo quise decir que incluso un solo valor podría ser grande. Esto es poco probable. "El reductor no almacena todos los valores en la memoria" es una afirmación verdadera. ¿Tiene sentido? –

+0

Sí. Gracias por la aclaración. ¿Tiene una referencia para esto, por casualidad? – Zach

2

No está del todo en la memoria, algunos de los que vienen desde el disco, mirando el código parece que el marco rompe el Iterable en segmentos, y los carga en la memoria forman el disco 1 por uno.

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

+0

¿Puede explicar cómo resolverá el problema? –

0

citado por otros usuarios, los datos entero no se carga en la memoria. Eche un vistazo a algunos de los parámetros mapred-site.xml del enlace de documentación Apache.

mapreduce.reduce.merge.inmem.threshold 

Valor por defecto: 1000. Es el umbral, en términos de la cantidad de archivos para el proceso de mezcla en memoria.

mapreduce.reduce.shuffle.merge.percent 

El valor predeterminado es 0.66. El umbral de uso en el que se iniciará una fusión en memoria, expresado como un porcentaje de la memoria total asignada para almacenar salidas de mapas en memoria, como se define en mapreduce.reduce.shuffle.input.buffer.percent.

mapreduce.reduce.shuffle.input.buffer.percent 

El valor predeterminado es 0.70. El porcentaje de memoria que se asignará desde el tamaño de almacenamiento dinámico máximo hasta el almacenamiento de las salidas del mapa durante la reproducción aleatoria.

mapreduce.reduce.input.buffer.percent 

El valor predeterminado es 0. El porcentaje de memoria relativo al tamaño máximo de almacenamiento dinámico para retener las salidas del mapa durante la reducción. Cuando finaliza la mezcla, cualquier salida de mapa restante en la memoria debe consumir menos de este umbral antes de que comience la reducción.

mapreduce.reduce.shuffle.memory.limit.percent 

El valor predeterminado es: 0.25. Porcentaje máximo del límite en memoria que puede consumir una sola mezcla