historia - Trabajando con divisiones de entrada(HADOOP)
hdfs que es (2)
Use el siguiente comando para obtener la lista de bloqueo para su archivo en HDFS
hdfs fsck PATH -files -blocks -locations
donde PATH es la ruta completa de HDFS donde está ubicado su archivo.
La salida (que se muestra a continuación parcialmente) será algo así (los números de línea 2, 3 ... ignoran)
Conectando a namenode a través de 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 iniciado por student6 (auth: SIMPLE) desde /172.31.11.124 para la ruta /student6/test.txt en Wed Mar 22 15:33:17 UTC 2017 /student6/test.txt 22 bytes, 1 bloque (es): 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]]
Copie la parte en negrita del comando de salida (excluyendo el _14433) como se muestra en la salida del ejemplo anterior
Vaya al sistema de archivos de Linux en su nodo de datos al directorio donde están almacenados los bloques (esto se indicará mediante el parámetro dfs.datanode.data.dir de hdfs-site.xml y buscará en el subárbol completo desde esa ubicación un nombre de archivo que tiene la cadena en negrita que acabas de copiar. Esto te dirá qué subdirectorio bajo dfs.datanode.data.dir contiene un archivo con esa cadena en su nombre (excluye cualquier nombre de archivo con el sufijo .meta). Una vez que hayas localizado ese nombre de archivo, puede ejecutar un comando cat de Linux en ese nombre de archivo para ver el contenido de su archivo.
Recuerde que aunque el archivo es un archivo HDFS, debajo de las carátulas, el archivo está realmente almacenado en el sistema de archivos de Linux y cada bloque del archivo HDFS es un archivo único de Linux. El bloque está identificado por el sistema de archivos de Linux con el nombre que se muestra en la secuencia en negrita del paso 2
Tengo un archivo .txt
la siguiente manera:
Esto es xyz
Esta es mi casa
Esta es mi PC
Esta es mi habitación
Esta es ubuntu PC xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxxxxxxxxxxxxxxxxxxx
(ignorando la línea en blanco después de cada registro)
Establecí el tamaño del bloque como 64 bytes . Lo que estoy tratando de verificar es si existe una situación en la que un solo registro se divide en dos bloques o no.
Ahora, lógicamente, dado que el tamaño de bloque es de 64 bytes , después de cargar el archivo a HDFS, debería crear 3 bloques de tamaño de 64,64,27 bytes respectivamente , lo que hace. Además, dado que el tamaño del primer bloque es de 64 bytes, debe contener solo los siguientes datos:
Esto es xyz
Esta es mi casa
Esta es mi PC
Esta es mi habitación
Th
Ahora quiero ver si el primer bloque es así o no, si navego por el HDFS a través del navegador y descargo el archivo, descarga todo el archivo, ni un solo bloque .
Así que decidí ejecutar un trabajo map-reduce que solo mostraría los valores de registro solamente. (Setting reducers=0
, y mapper output como context.write(null,record_value)
, también cambiando el delimitador predeterminado a ""
)
Ahora, mientras se ejecuta el trabajo, los contadores de trabajo muestran 3 divisiones , lo cual es obvio, pero después de completarlo, cuando miro el directorio de salida, muestra 3 archivos de salida del mapeador , de los cuales 2 están vacíos y el primer archivo de salida del mapeador tiene todo el contenido del archivo tal como es.
Puede alguien ayudarme con esto? ¿Existe la posibilidad de que las versiones más nuevas de hadoop manejen registros incompletos automáticamente?
Pasos seguidos para reproducir el escenario
1) Creó un archivo sample.txt
con el contenido con un tamaño total ~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) Se agregó la propiedad a hdfs-site.xml
<property>
<name>dfs.namenode.fs-limits.min-block-size</name>
<value>10</value>
</property>
y cargado en HDFS con tamaño de bloque como 64B
.
hdfs dfs -Ddfs.bytes-per-checksum=16 -Ddfs.blocksize=64 -put sample.txt /
Esto creó tres bloques de tamaños 64B
, 64B
y 25B
.
Contenido en Block0
:
This is xyz
This is my home
This is my PC
This is my room
This i
Contenido en Block1
:
s ubuntu PC xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx xx
Contenido en Block2
:
xx xxxxxxxxxxxxxxxxxxxxx
3) Un simple mapper.py
#!/usr/bin/env python
import sys
for line in sys.stdin:
print line
4) Hadoop Streaming con 0
reductores:
yarn jar hadoop-streaming-2.7.1.jar -Dmapreduce.job.reduces=0 -file mapper.py -mapper mapper.py -input /sample.txt -output /splittest
El trabajo se ejecutó con 3 divisiones de entrada invocando 3 correlacionadores y generó 3 archivos de salida con un archivo que contiene todo el contenido de sample.txt
y el resto de los archivos 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
El archivo sample.txt
se divide en 3 divisiones y estas divisiones se asignan a cada asignador como,
mapper1: start=0, length=64B
mapper2: start=64, length=64B
mapper3: start=128, length=25B
Esto solo determina qué parte del archivo debe leer el asignador, no es necesario que tenga que ser exacto. El contenido real que lee un asignador está determinado por FileInputFormat y sus límites, aquí TextFileInputFormat
.
Utiliza LineRecordReader
para leer el contenido de cada división y usa /n
como delimitador (límite de línea). Para un archivo que no está comprimido, cada asignador lee las líneas como se explica a continuación.
Para el mapeador cuyo índice de inicio es 0, la lectura de línea comienza desde el inicio de la división. Si la división termina con /n
la lectura termina en el límite dividido, de lo contrario, busca la primera /n
publica la longitud de la división asignada (aquí 64B
). Tal que no termine procesando una línea parcial.
Para todos los demás mapeadores (start index! = 0), comprueba si el carácter anterior de su índice de inicio ( start - 1
) es /n
, si es así, lee el contenido desde el inicio de la división, de lo contrario omite el contenido que está presente entre su índice de inicio y el primer carácter /n
encontrado en esa división (ya que este es manejado por otro asignador) y comienza a leer desde el primero /n
.
Aquí, mapper1
(el índice de inicio es 0) comienza con Block0
cuya división termina en el medio de una línea. Por lo tanto, continúa leyendo la línea que consume todo el Block1
y, dado que el Block1
no tiene un carácter /n
, el mapper1
continúa leyendo hasta que encuentra un /n
que también termina consumiendo todo el Block2
. Así es como todo el contenido de sample.txt
terminó en salida de mapeador único.
mapper2
(start index! = 0), un caracter que precede a su índice de inicio no es /n
, así que se salta la línea y termina sin contenido. Salida de mapeador vacía. mapper3
tiene el mismo escenario que mapper2
.
sample.txt
así para ver resultados diferentes 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