2012-06-13 10 views
6

Sto scrivendo un lavoro MapReduce che può finire con un enorme numero di valori nel riduttore. Sono preoccupato che tutti questi valori vengano caricati in memoria contemporaneamente.Valori di riduzione Hadoop in memoria?

L'implementazione sottostante dello Iterable<VALUEIN> values carica i valori in memoria quando sono necessari? Hadoop: la Guida definitiva sembra suggerire questo, ma non fornisce una risposta "definitiva".

L'uscita del riduttore sarà molto più massiccia dei valori immessi, ma credo che l'output sia scritto sul disco secondo necessità.

risposta

12

Stai leggendo il libro correttamente. Il riduttore non memorizza tutti i valori in memoria. Invece, durante il looping attraverso l'elenco dei valori Iterable, ogni istanza di Object viene riutilizzata, quindi mantiene solo un'istanza in un dato momento.

Ad esempio nel codice seguente, l'array ArrayList avrà la dimensione prevista dopo il ciclo ma ogni elemento sarà lo stesso b/c l'istanza di testo Val viene riutilizzata ogni iterazione.

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

(Se per qualche ragione avete voglia di intraprendere ulteriori azioni per ogni val, si dovrebbe fare una copia profonda e poi memorizzarlo.)

Naturalmente anche un solo valore potrebbe essere più grande di memoria . In questo caso, è consigliabile che lo sviluppatore esegua dei passi per ridurre i dati nel Mapper precedente, in modo che il valore non sia troppo grande.

UPDATE: vedere le pagine 199-200 di 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

Sono confuso dalla risposta. Per prima cosa dici "il riduttore non memorizza tutti i valori in memoria", il che implica che i valori Iterable carichi secondo necessità. In seguito, si dice, "anche una singola istanza di valori potrebbe essere più grande della memoria", il che implica che l'elenco di valori viene prima caricato in memoria. Puoi chiarire per favore? – Zach

+0

Modificato per chiarire. Volevo solo che anche un singolo valore potesse essere grande. Questo è improbabile. "Il riduttore non memorizza tutti i valori in memoria" è una vera affermazione. Ha senso? –

+0

Sì. Grazie per il chiarimento. Hai un riferimento per questo, per caso? – Zach

2

Non è del tutto in memoria, alcune delle quali proviene dal disco, guardando il codice sembra quadro rompe l'Iterable in segmenti, e caricare loro forma disco nella memoria 1 per uno.

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

+0

Puoi spiegare come risolverà il problema? –

0

Come citato da altri utenti, tutto il dato non è stato caricato in memoria. Dai un'occhiata ad alcuni dei parametri mapred-site.xml dal link alla documentazione Apache.

mapreduce.reduce.merge.inmem.threshold 

Valore di default: 1000. E 'la soglia, in termini di numero di file per il processo di unione in memoria.

mapreduce.reduce.shuffle.merge.percent 

Il valore predefinito è 0,66. La soglia di utilizzo a cui verrà avviata l'unione in memoria, espressa come percentuale della memoria totale allocata per l'archiviazione delle uscite della mappa in memoria, come definito da mapreduce.reduce.shuffle.input.buffer.percent.

mapreduce.reduce.shuffle.input.buffer.percent 

Il valore predefinito è 0,70. La percentuale di memoria da allocare dalla dimensione massima dell'heap per memorizzare gli output delle mappe durante lo shuffle.

mapreduce.reduce.input.buffer.percent 

valore predefinito è 0. La percentuale di relativa memoria-al massimo dimensione- mucchio di trattenere uscite sugli durante il ridurre. Al termine dello shuffle, tutte le restanti uscite della mappa in memoria devono consumare meno di questa soglia prima che possa iniziare la riduzione.

mapreduce.reduce.shuffle.memory.limit.percent 

Il valore predefinito è: 0,25. Percentuale massima del limite di memoria che un singolo shuffle può consumare

Problemi correlati