tutoriel - tp hadoop




Travailler avec des divisions d'entrée(HADOOP) (2)

  1. Utilisez la commande suivante pour obtenir la liste de blocage pour votre fichier sur HDFS

    hdfs fsck PATH -files -blocks -locations

où PATH est le chemin complet HDFS où se trouve votre fichier.

  1. La sortie (montrée ci-dessous partiellement) sera quelque chose comme ça (les numéros de ligne 2, 3 ... ignorer)

    Connexion à namenode via http://ec2-54-235-1-193.compute-1.amazonaws.com:50070/fsck?ugi=student6&files=1&blocks=1&locations=1&path=%2Fstudent6%2Ftest.txt FSCK démarré par student6 (auth: SIMPLE) à partir de /172.31.11.124 pour le chemin /student6/test.txt at Mer Mar 22 15:33:17 UTC 2017 /student6/test.txt 22 octets, 1 bloc (s): OK 0. BP-944036569 -172.31.11.124-1467635392176: blk_1073755254 _14433 len = 22 repl = 1 [DatanodeInfoWithStorage [172.31.11.124:50010,DS-4a530a72-0495-4b75-a6f9-75bdb8ce7533,DISK]]

  2. Copiez la partie en gras de la commande de sortie (à l'exclusion du _14433) comme indiqué dans l'exemple de sortie ci-dessus

  3. Aller au système de fichiers Linux sur votre datanode dans le répertoire où les blocs sont stockés (ceci sera pointé par le paramètre dfs.datanode.data.dir de hdfs-site.xml et chercher dans le sous-arbre entier à partir de cet emplacement pour un nom de fichier a la chaîne en gras que vous venez de copier Cela vous indiquera quel sous-répertoire sous dfs.datanode.data.dir contient un fichier avec cette chaîne dans son nom (excluez tout nom de fichier avec le suffixe .meta.) Une fois que vous avez trouvé un tel nom de fichier, peut exécuter une commande Linux cat sur ce nom de fichier pour voir le contenu de votre fichier.

  4. Rappelez-vous bien que le fichier est un fichier HDFS, sous les couvertures le fichier est en fait stocké sur le système de fichiers Linux et chaque bloc du fichier HDFS est un fichier Linux unique. Le bloc est identifié par le système de fichiers Linux avec le nom indiqué dans la chaîne en gras de l'étape 2

J'ai un fichier .txt comme suit:

C'est xyz

C'est ma maison

C'est mon PC

C'est ma chambre

Ceci est ubuntu PC xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxxxxxxxxxxxxxxxxxxx

(en ignorant la ligne vide après chaque enregistrement)

J'ai défini la taille du bloc comme 64 octets . Ce que j'essaie de vérifier, c'est s'il existe une situation où un seul enregistrement est divisé en deux blocs ou non.

Maintenant, logiquement, puisque la taille du bloc est de 64 octets , après avoir téléchargé le fichier sur HDFS, il devrait créer 3 blocs de taille 64,64,27 octets respectivement , ce qu'il fait. De plus, puisque la taille du premier bloc est de 64 octets, il ne doit contenir que les données suivantes:

C'est xyz

C'est ma maison

C'est mon PC

C'est ma chambre

Th

Maintenant, je veux voir si le premier bloc est comme ça ou pas, si je navigue sur le HDFS via le navigateur et télécharge le fichier, il télécharge le fichier entier pas un seul bloc .

J'ai donc décidé d'exécuter un travail de réduction de mappage qui n'afficherait que les valeurs d'enregistrement (Définition des reducers=0 et mappage en tant que context.write(null,record_value) , en changeant également le délimiteur par défaut à "" )

Maintenant, lors de l'exécution du travail, les compteurs de travail montrent 3 divisions , ce qui est évident, mais après l'achèvement lorsque je vérifie le répertoire de sortie, il montre 3 fichiers de sortie mapper dont 2 sont vides et le premier fichier de sortie de mappeur a tout le contenu fichier tel quel.

Est-ce que quelqu'un peut m'aider avec ça? Est-il possible que les nouvelles versions de hadoop traitent automatiquement les enregistrements incomplets?


Les étapes suivies pour reproduire le scénario
1) Création d'un fichier sample.txt avec le contenu d'une taille totale ~153B

cat sample.txt

This is xyz
This is my home
This is my PC
This is my room
This is ubuntu PC xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxxxxxxxxxxxxxxxxxxx

2) Ajout de la propriété à hdfs-site.xml

<property>
    <name>dfs.namenode.fs-limits.min-block-size</name>
    <value>10</value>
</property>

et chargé dans HDFS avec la taille de bloc comme 64B .

hdfs dfs -Ddfs.bytes-per-checksum=16 -Ddfs.blocksize=64 -put sample.txt /

Cela a créé trois blocs de tailles 64B , 64B et 25B .

Contenu dans Block0 :

This is xyz
This is my home
This is my PC
This is my room
This i

Contenu dans le Block1 :

s ubuntu PC xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx

Contenu dans le Block2 :

xx xxxxxxxxxxxxxxxxxxxxx

3) Un mapper.py simple

#!/usr/bin/env python

import sys

for line in sys.stdin:
    print line

4) Hadoop Streaming avec 0 réducteurs:

yarn jar hadoop-streaming-2.7.1.jar -Dmapreduce.job.reduces=0 -file mapper.py -mapper mapper.py -input /sample.txt -output /splittest

Le travail s'est exécuté avec 3 divisions d'entrée invoquant 3 mappeurs et a généré 3 fichiers de sortie avec un fichier contenant tout le contenu de sample.txt et les autres fichiers 0B .

hdfs dfs -ls /splittest

-rw-r--r--   3 user supergroup          0 2017-03-22 11:13 /splittest/_SUCCESS
-rw-r--r--   3 user supergroup        168 2017-03-22 11:13 /splittest/part-00000
-rw-r--r--   3 user supergroup          0 2017-03-22 11:13 /splittest/part-00001
-rw-r--r--   3 user supergroup          0 2017-03-22 11:13 /splittest/part-00002

Le fichier sample.txt est divisé en 3 divisions et ces divisions sont assignées à chaque mappeur en tant que,

mapper1: start=0, length=64B
mapper2: start=64, length=64B
mapper3: start=128, length=25B

Cela détermine seulement quelle partie du fichier doit être lue par le mappeur, pas nécessaire qu'elle soit exacte. Le contenu réel qui est lu par un mappeur est déterminé par FileInputFormat et ses limites, ici TextFileInputFormat .

Cela utilise LineRecordReader pour lire le contenu de chaque division et utilise \n comme délimiteur (limite de ligne). Pour un fichier qui n'est pas compressé, les lignes sont lues par chaque mappeur comme expliqué ci-dessous.

Pour le mappeur dont l'index de départ est 0, la lecture de ligne commence à partir du début de la scission. Si la division se termine par \n la lecture se termine à la limite de la séparation, sinon elle cherche le premier \n après la longueur de la division assignée (ici 64B ). De telle sorte qu'il ne finit pas de traiter une ligne partielle.

Pour tous les autres mappeurs (start index! = 0), il vérifie si le caractère précédent de son index de départ ( start - 1 ) est \n , si oui il lit le contenu depuis le début de la scission sinon il ignore le contenu est présent entre son index de départ et le premier caractère \n rencontré dans ce split (car ce contenu est géré par un autre mappeur) et commence à lire depuis le premier \n .

Ici, mapper1 (l'index de départ est 0) commence par Block0 dont la division se termine au milieu d'une ligne. Ainsi, il continue à lire la ligne qui consomme le Block1 et puisque le Block1 n'a pas de caractère \n , mapper1 continue à lire jusqu'à ce qu'il trouve un \n qui se termine par consommer tout le Block2 également. C'est ainsi que tout le contenu de sample.txt s'est retrouvé dans une sortie de mappeur unique.

mapper2 (start index! = 0), un caractère précédant son index de départ n'est pas un \n , donc saute la ligne et finit sans contenu. Sortie de mappeur vide. mapper3 a le même scénario que mapper2 .

Essayez de changer le contenu de sample.txt comme ceci pour voir des résultats différents

This is xyz
This is my home
This is my PC
This is my room
This is ubuntu PC xxxx xxxx xxxx xxxx 
xxxx xxxx xxxx xxxx xxxx xxxx xxxx 
xxxxxxxxxxxxxxxxxxxxx