Tengo un archivo .txt de 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)

He configurado 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 del bloque es 64 bytes , después de cargar el archivo en HDFS, debe crear 3 bloques del tamaño 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 busco el HDFS a través del navegador y descargo el archivo, descarga todo el archivo, no un solo bloque .

Así que decidí ejecutar un trabajo de reducción de mapas que solo mostraría los valores de registro únicamente (Configuración reducers=0, y salida del mapeador 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 verifico el directorio de salida, muestra 3 archivos de salida del mapeador de los cuales 2 están vacías y el primer archivo de salida del asignador tiene todo el contenido del archivo tal como está.

Puede alguien ayudarme con esto? ¿Existe la posibilidad de que las versiones más recientes de hadoop manejen registros incompletos automáticamente?

10
User9523 16 mar. 2017 a las 21:44

2 respuestas

La mejor respuesta

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 el 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 reductores 0 :

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 asignadores y generó 3 archivos de salida con un archivo que contiene todo el contenido de sample.txt y el resto 0B archivos.

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 ser leído por el mapeador, no es necesario que sea exacto. FileInputFormat y sus límites determinan el contenido real que lee un asignador, aquí TextFileInputFormat.

Esto usa 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 mapeador lee las líneas como se explica a continuación.

Para el asignador 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 de división; de lo contrario, busca la primera \n publicación de la longitud de la división asignada (aquí 64B). De tal manera que no termine procesando una línea parcial.

Para todos los otros mapeadores (¡índice de inicio! = 0), verifica si el carácter anterior de su índice de inicio (start - 1) es \n, en caso afirmativo, lee el contenido desde el inicio de la división. 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 contenido es manejado por otro mapeador) y comienza a leer desde el primer \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 Block1 no tiene un carácter \n, mapper1 continúa leyendo hasta que encuentra un {{X6 }} que termina con el consumo de Block2 completo también. Así es como todo el contenido de sample.txt terminó en salida de mapeador único.

mapper2 (¡índice de inicio! = 0), un carácter que precede a su índice de inicio no es un \n, por lo que omite la línea y termina sin contenido. Salida del asignador vacío. mapper3 tiene el mismo escenario que mapper2.


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
7
franklinsijo 25 mar. 2017 a las 02:33
  1. 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 se encuentra su archivo.

  1. La salida (que se muestra a continuación parcialmente) será algo como esto (los números de línea 2, 3 ... ignorar)

    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 el miércoles 22 de marzo a las 15:33:17 UTC de 2017 /student6/test.txt 22 bytes, 1 bloque (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, DISCO]]

  2. Copie la parte en negrita del comando de salida (excluyendo el _14433) como se muestra en la salida de ejemplo anterior

  3. Vaya al sistema de archivos de Linux en su nodo de datos al directorio donde se almacenan los bloques (esto será señalado por el parámetro dfs.datanode.data.dir de hdfs-site.xml y busque en el subárbol completo desde esa ubicación un nombre de archivo que tiene la cadena en negrita que acaba de copiar. Eso le dirá qué subdirectorio bajo dfs.datanode.data.dir contiene un archivo con esa cadena en su nombre (excluya cualquier nombre de archivo con el sufijo .meta). Una vez que haya localizado dicho nombre de archivo, puede ejecutar un comando cat de Linux en ese nombre de archivo para ver el contenido de su archivo.

  4. Recuerde que aunque el archivo es un archivo HDFS, en realidad el archivo se almacena en el sistema de archivos Linux y cada bloque del archivo HDFS es un archivo Linux exclusivo. El sistema de archivos de Linux identifica el bloque con el nombre que se muestra en la cadena en negrita del paso 2

1
BDBoss 22 mar. 2017 a las 15:42