web-dev-qa-db-fra.com

Le conteneur fonctionne au-delà des limites de la mémoire

Dans Hadoop v1, j'ai attribué à chaque mappeur et réducteur 7 emplacements d'une taille de 1 Go, mes mappeurs et réducteurs fonctionnent correctement. Ma machine a 8G de mémoire, 8 processeurs. Maintenant, avec YARN, lorsque je lance la même application sur la même machine, j'ai une erreur de conteneur. Par défaut, j'ai ces paramètres:

  <property>
    <name>yarn.scheduler.minimum-allocation-mb</name>
    <value>1024</value>
  </property>
  <property>
    <name>yarn.scheduler.maximum-allocation-mb</name>
    <value>8192</value>
  </property>
  <property>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>8192</value>
  </property>

Cela m'a donné une erreur:

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.

J'ai ensuite essayé de définir la limite de mémoire dans mapred-site.xml:

  <property>
    <name>mapreduce.map.memory.mb</name>
    <value>4096</value>
  </property>
  <property>
    <name>mapreduce.reduce.memory.mb</name>
    <value>4096</value>
  </property>

Mais toujours obtenir une erreur:

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.

Je ne comprends pas pourquoi la tâche de la carte nécessite autant de mémoire. Selon ma compréhension, 1 Go de mémoire est suffisant pour ma tâche de mappage/réduction. Pourquoi, alors que j'attribue plus de mémoire au conteneur, la tâche en utilise plus? Est-ce parce que chaque tâche est plus fractionnée? Je pense qu'il est plus efficace de réduire un peu la taille du conteneur et de créer plus de conteneurs afin que davantage de tâches s'exécutent en parallèle. Le problème est comment puis-je m'assurer que chaque conteneur ne se verra pas attribuer plus de divisions qu'il ne peut en gérer?

70
Lishu

Vous devez également configurer correctement les allocations de mémoire maximales pour MapReduce. De ce tutoriel HortonWorks :

[...]

Chaque machine de notre cluster dispose de 48 Go de RAM. Une partie de cette RAM devrait être> réservée à l'utilisation du système d'exploitation. Sur chaque nœud, nous assignerons 40 Go RAM pour> YARN et en conserverons 8 pour le système d'exploitation.

Pour notre exemple de cluster, nous avons le minimum RAM pour un conteneur (yarn.scheduler.minimum-allocation-mb) = 2 Go. Nous allons donc assigner 4 Go pour les conteneurs de tâches de mappage et 8 Go pour les conteneurs de tâches de réduction.

Dans mapred-site.xml:

mapreduce.map.memory.mb: 4096

mapreduce.reduce.memory.mb: 8192

Chaque conteneur exécutera des machines virtuelles pour les tâches Mapper et Réduire. La taille du segment de mémoire de la machine virtuelle Java doit être définie sur une valeur inférieure à celle de la mémoire de mappage et de réduction définie ci-dessus, afin qu'elles se situent dans les limites de la mémoire du conteneur allouée par YARN.

Dans mapred-site.xml:

mapreduce.map.Java.opts: -Xmx3072m

mapreduce.reduce.Java.opts: -Xmx6144m

Les paramètres ci-dessus configurent la limite supérieure de la RAM physique _ que les tâches Mapper et Réduire utiliseront .

Résumer:

  1. Dans YARN, vous devriez utiliser les configs mapreduce, pas ceux mapred. EDIT: Ce commentaire n'est plus applicable maintenant que vous avez modifié votre question.
  2. Ce que vous configurez correspond en réalité au nombre de demandes que vous souhaitez effectuer et non au maximum à allouer.
  3. Les limites maximales sont configurées avec les paramètres Java.opts énumérés ci-dessus.

Enfin, vous voudrez peut-être vérifier cet autre SO question qui décrit un problème similaire (et sa solution).

90
cabad

Un contrôle est placé au niveau des fils pour le rapport d'utilisation de la mémoire Vertual et Physique. Le problème n’est pas seulement dû au fait que VM n’a pas suffisamment de mémoire physique. Mais c’est parce que l’utilisation de la mémoire virtuelle est plus importante que prévu pour une mémoire physique donnée.

Remarque : Cela se produit sous Centos/RHEL 6 en raison de son allocation agressive de mémoire virtuelle.

Il peut être résolu soit par:

  1. Désactivez la vérification de l'utilisation de la mémoire virtuelle en définissant yarn.nodemanager.vmem-check-enabled sur false ;

  2. Augmentez le ratio VM: PM en définissant yarn.nodemanager.vmem-pmem-ratio sur une valeur plus élevée.

Références :

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

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

Ajouter la propriété suivante dans yarn-site.xml

 <property>
   <name>yarn.nodemanager.vmem-check-enabled</name>
    <value>false</value>
    <description>Whether virtual memory limits will be enforced for containers</description>
  </property>
 <property>
   <name>yarn.nodemanager.vmem-pmem-ratio</name>
    <value>4</value>
    <description>Ratio between virtual memory to physical memory when setting memory limits for containers</description>
  </property>
42
Sanjiv

J'ai eu un problème très similaire en utilisant Hive dans EMR. Aucune des solutions existantes ne fonctionnait pour moi - c’est-à-dire qu’aucune des configurations mapreduce ne fonctionnait pour moi; et mettre non plus yarn.nodemanager.vmem-check-enabled sur false.

Cependant, ce qui a fini par fonctionner a été de définir tez.am.resource.memory.mb, par exemple:

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

Un autre paramètre à considérer est le yarn.app.mapreduce.am.resource.mb

12
hiroprotagonist

Je ne peux pas commenter la réponse acceptée en raison de la mauvaise réputation. Cependant, j'aimerais ajouter que ce comportement est voulu par la conception même. NodeManager tue votre conteneur. On dirait que vous essayez d'utiliser le streaming hadoop, qui est exécuté en tant que processus enfant de la tâche de réduction de carte. NodeManager surveille l’ensemble de l’arborescence de processus de la tâche et s’il utilise plus de mémoire que le maximum défini dans mapreduce.map.memory.mb ou mapreduce.reduce.memory.mb, nous nous attendrions à ce que Nodemanager tue la tâche, sinon votre tâche est de voler de la mémoire appartenant à d'autres conteneurs, ce que vous ne voulez pas.

8
Brian G

Lorsque je travaillais avec spark dans EMR, j’avais le même problème et la configuration de maximizeResourceAllocation=true s’est révélée efficace. J'espère que ça aide quelqu'un. Vous devez le définir lorsque vous créez le cluster. À partir du EMR docs:

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

Où myConfig.json devrait dire:

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

Nous avons également fait face à ce problème récemment. Si le problème est lié à la mémoire du mappeur, voici quelques points à vérifier.

  • Vérifiez si le combinateur est activé ou non ? Si oui, cela signifie que la logique de réduction doit être exécutée sur tous les enregistrements (sortie du mappeur). Cela se produit en mémoire. En fonction de votre application, vous devez vérifier si l'activation du combinateur est utile ou non. Le compromis se situe entre les octets de transfert réseau et le temps pris/mémoire/CPU pour la logique de réduction sur le nombre d'enregistrements 'X'.
    • Si vous pensez que le combineur n’a pas beaucoup de valeur, désactivez-le.
    • Si vous avez besoin d'un combinateur et que 'X' est un nombre énorme (disons des millions d'enregistrements), envisagez de modifier votre logique de fractionnement (pour les formats d'entrée par défaut, utilisez une taille de bloc inférieure, normalement 1 taille de bloc = 1 fractionnée) pour mapper un nombre inférieur d'enregistrements à un fichier. mappeur unique.
  • Nombre d'enregistrements traités dans un seul mappeur. N'oubliez pas que tous ces enregistrements doivent être triés en mémoire (la sortie du mappeur est triée). Envisagez de définir mapreduce.task.io.sort.mb (la valeur par défaut est 200 Mo), si nécessaire. mapred-configs.xml
  • Si l’une des solutions ci-dessus ne vous a pas aidé, essayez d’exécuter la logique du mappeur en tant qu’application autonome et profilez-la à l’aide d’un profileur (comme JProfiler) et voyez où la mémoire sera utilisée. Cela peut vous donner de très bonnes idées.
1
Rathan