Il contenitore sta funzionando oltre i limiti di memoria

In Hadoop v1, ho assegnato ogni 7 slot di mapper e riduttore con dimensioni di 1 GB, i miei mapper e riduttori funzionano bene. La mia macchina ha 8G di memoria, 8 processori. Ora con YARN, quando si esegue la stessa applicazione sulla stessa macchina, ho ricevuto un errore del contenitore. Per impostazione predefinita, ho queste impostazioni:

 yarn.scheduler.minimum-allocation-mb 1024   yarn.scheduler.maximum-allocation-mb 8192   yarn.nodemanager.resource.memory-mb 8192  

Mi ha dato errore:

 Container [pid=28920,containerID=container_1389136889967_0001_01_000121] is running beyond virtual memory limits. Current usage: 1.2 GB of 1 GB physical memory used; 2.2 GB of 2.1 GB virtual memory used. Killing container. 

Ho quindi provato a impostare il limite di memoria in mapred-site.xml:

   mapreduce.map.memory.mb 4096   mapreduce.reduce.memory.mb 4096  

Ma continuiamo ad avere errori:

 Container [pid=26783,containerID=container_1389136889967_0009_01_000002] is running beyond physical memory limits. Current usage: 4.2 GB of 4 GB physical memory used; 5.2 GB of 8.4 GB virtual memory used. Killing container. 

Sono confuso perché il compito della mappa ha bisogno di tanta memoria. Nella mia comprensione, 1 GB di memoria è sufficiente per la mia mappa / ridurre il compito. Perché quando assegno più memoria al contenitore, l’attività utilizza di più? È perché ogni attività ottiene più divisioni? Ritengo che sia più efficiente ridurre leggermente le dimensioni del contenitore e creare più contenitori, in modo che più attività vengano eseguite in parallelo. Il problema è: come posso assicurarmi che ad ogni contenitore non vengano assegnate più divisioni di quante ne possa gestire?

Dovresti anche configurare correttamente le allocazioni massime di memoria per MapReduce. Da questo tutorial di HortonWorks :

[…]

Ogni macchina nel nostro cluster ha 48 GB di RAM. Alcune di queste RAM dovrebbero essere> riservate all’utilizzo del sistema operativo. Su ciascun nodo, assegneremo 40 GB di RAM per> YARN da utilizzare e manterremo 8 GB per il sistema operativo

Per il nostro cluster di esempio, abbiamo la RAM minima per un container (yarn.scheduler.minimum-allocation-mb) = 2 GB. Assegneremo quindi 4 GB per i contenitori delle attività Mappa e 8 GB per Ridurre i contenitori delle attività.

In mapred-site.xml:

mapreduce.map.memory.mb : 4096

mapreduce.reduce.memory.mb : 8192

Ogni Container eseguirà JVM per la mappa e ridurrà le attività. La dimensione dell’heap JVM deve essere impostata su un valore inferiore rispetto a Mappa e su Riduci la memoria definita sopra, in modo che si trovino entro i limiti della memoria del contenitore allocata da YARN.

In mapred-site.xml:

mapreduce.map.java.opts : -Xmx3072m

mapreduce.reduce.java.opts : -Xmx6144m

Le impostazioni precedenti configurano il limite superiore della RAM fisica che verranno utilizzate dalle attività Mappa e Riduzione .

Riassumendo:

  1. In YARN, dovresti usare le mapreduce , non quelle con mappa. EDIT: questo commento non è più applicabile ora che hai modificato la tua domanda.
  2. Quello che stai configurando è in realtà quanto vuoi richiedere, non il massimo da allocare.
  3. I limiti massimi sono configurati con le impostazioni java.opts elencate sopra.

Infine, potresti voler controllare questa altra domanda SO che descrive un problema simile (e una soluzione).

È disponibile un controllo a livello di filato per il rapporto di utilizzo memoria fisica e fisica. Il problema non è solo che la VM non ha sufficiente memoria fisica. Ma è perché l’utilizzo della memoria virtuale è più del previsto per una determinata memoria fisica.

Nota : questo sta accadendo su Centos / RHEL 6 a causa della sua allocazione aggressiva della memoria virtuale.

Può essere risolto da:

  1. Disabilitare il controllo dell’utilizzo della memoria virtuale impostando yarn.nodemanager.vmem-check-enabled su false ;

  2. Aumenta VM: rapporto PM impostando il valore di filato.nodemanager.vmem-pmem su un valore superiore.

Riferimenti :

https://issues.apache.org/jira/browse/HADOOP-11364

http://blog.cloudera.com/blog/2014/04/apache-hadoop-yarn-avoiding-6-time-consuming-gotchas/

Aggiungi la seguente proprietà in yarn-site.xml

   yarn.nodemanager.vmem-check-enabled false Whether virtual memory limits will be enforced for containers   yarn.nodemanager.vmem-pmem-ratio 4 Ratio between virtual memory to physical memory when setting memory limits for containers  

Ho avuto un problema molto simile usando HIVE in EMR. Nessuna delle soluzioni esistenti ha funzionato per me, cioè nessuna delle configurazioni di mapreduce ha funzionato per me; e nemmeno l’impostazione di yarn.nodemanager.vmem-check-enabled su false.

Tuttavia, ciò che ha finito per funzionare era impostare tez.am.resource.memory.mb , ad esempio:

 hive -hiveconf tez.am.resource.memory.mb=4096 

Un’altra impostazione da considerare per il tweaking è yarn.app.mapreduce.am.resource.mb

Non posso commentare la risposta accettata, a causa della scarsa reputazione. Tuttavia, vorrei aggiungere, questo comportamento è di progettazione. Il NodeManager sta uccidendo il tuo contenitore. Sembra che tu stia cercando di usare lo streaming hadoop che è in esecuzione come un processo secondario dell’attività di riduzione della mappa. Il NodeManager monitora l’intero albero del processo dell’attività e se consuma più memoria rispetto al massimo impostato in mapreduce.map.memory.mb o mapreduce.reduce.memory.mb rispettivamente, ci si aspetterebbe che il Nodemanager uccida l’attività, altrimenti il tuo compito è rubare la memoria che appartiene ad altri contenitori, che non vuoi.

Mentre lavoravo con la scintilla in EMR stavo avendo lo stesso problema e l’impostazione maximizeResourceAllocation=true fatto il trucco; spero che aiuti qualcuno. Devi impostarlo quando crei il cluster. Dai documenti EMR:

 aws emr create-cluster --release-label emr-5.4.0 --applications Name=Spark \ --instance-type m3.xlarge --instance-count 2 --service-role EMR_DefaultRole --ec2-attributes InstanceProfile=EMR_EC2_DefaultRole --configurations https://s3.amazonaws.com/mybucket/myfolder/myConfig.json 

Dove myConfig.json dovrebbe dire:

 [ { "Classification": "spark", "Properties": { "maximizeResourceAllocation": "true" } } ] 

Abbiamo anche affrontato questo problema di recente. Se il problema è legato alla memoria del mapper, un paio di cose che vorrei suggerire che debbano essere controllate sono.

  • Controlla se il combinatore è abilitato o no ? Se sì, significa che la logica di riduzione deve essere eseguita su tutti i record (output di mapper). Questo succede in memoria. In base alla tua applicazione, devi verificare se abilitare o meno il combinatore. Il trade off è tra i byte di trasferimento di rete e il tempo impiegato / memoria / CPU per la logica di riduzione sul numero di record “X”.
    • Se ritieni che il combinatore non abbia molto valore, disabilitalo.
    • Se hai bisogno di un combinatore e la “X” è un numero enorme (ad esempio milioni di record), considera la modifica della logica di divisione (per i formati di input predefiniti utilizzare meno blocchi, normalmente 1 dimensione blocco = 1 divisione) per mappare un numero inferiore di record single mapper.
  • Numero di record elaborati in un singolo mapper. Ricorda che tutti questi record devono essere ordinati in memoria (l’output del mapper è ordinato). Considerare l’impostazione mapreduce.task.io.sort.mb (il valore predefinito è 200MB) su un valore più alto se necessario. mapred-configs.xml
  • Se uno dei precedenti non è stato di aiuto, provare a eseguire la logica del mapping come applicazione autonoma e creare un profilo dell’applicazione utilizzando un Profiler (come JProfiler) e vedere dove viene utilizzata la memoria. Questo può darti informazioni molto buone.