¿Cómo se dividen los registros de proceso de Hadoop a través de los límites del bloque?



Answers

El algoritmo Map Reduece no funciona en bloques físicos del archivo. Funciona en splits de entrada lógica. La división de entrada depende del lugar donde se escribió el registro. Un registro puede abarcar dos Mappers.

La forma en que HDFS se ha configurado, descompone archivos muy grandes en bloques grandes (por ejemplo, mide 128 MB) y almacena tres copias de estos bloques en diferentes nodos del clúster.

HDFS no tiene conocimiento del contenido de estos archivos. Se puede haber iniciado un registro en el Bloque-a, pero el final de ese registro puede estar presente en el Bloque-b .

Para resolver este problema, Hadoop usa una representación lógica de los datos almacenados en bloques de archivos, conocidos como divisiones de entrada. Cuando un cliente de trabajo de MapReduce calcula las divisiones de entrada , se da cuenta de dónde comienza el primer registro completo en un bloque y dónde termina el último registro en el bloque .

El punto clave :

En los casos en que el último registro en un bloque es incompleto, la división de entrada incluye información de ubicación para el próximo bloque y el desplazamiento de bytes de los datos necesarios para completar el registro.

Echa un vistazo al diagrama a continuación.

Eche un vistazo a este article y a la pregunta relacionada con SE: Acerca de la división de archivos Hadoop / HDFS

Se pueden leer más detalles de la documentation

El marco Map-Reduce depende del InputFormat del trabajo para:

  1. Valide la especificación de entrada del trabajo.
  2. Separe los archivos de entrada en InputSplits lógicos, cada uno de los cuales se asignará a un Mapper individual.
  3. Cada InputSplit se asigna a un Mapper individual para su procesamiento. Split podría ser una tupla . InputSplit[] getSplits(JobConf job,int numSplits ) es la API para encargarse de estas cosas.

FileInputFormat , que amplía el InputFormat getSplits () de InputFormat implementado. Eche un vistazo a las grepcode internas de este método en grepcode

Question

De acuerdo con Hadoop - The Definitive Guide

Los registros lógicos que FileInputFormats definen generalmente no se ajustan perfectamente a los bloques HDFS. Por ejemplo, los registros lógicos de un TextInputFormat son líneas, que cruzarán los límites de HDFS la mayoría de las veces. Esto no influye en el funcionamiento de su programa (las líneas no se pierden ni se rompen, por ejemplo), pero vale la pena conocerlo, ya que significa que los mapas de datos locales (es decir, los mapas que se ejecutan en el mismo host que su datos de entrada) realizará algunas lecturas remotas. La ligera sobrecarga que esto causa normalmente no es significativa.

Supongamos que una línea de registro se divide en dos bloques (b1 y b2). El mapeador que procesa el primer bloque (b1) notará que la última línea no tiene un separador EOL y obtiene el resto de la línea del próximo bloque de datos (b2).

¿Cómo determina el mapper que procesa el segundo bloque (b2) que el primer registro está incompleto y debe procesar a partir del segundo registro en el bloque (b2)?




Desde el código fuente de hadoop de LineRecordReader.java el constructor: encuentro algunos comentarios:

// If this is not the first split, we always throw away first record
// because we always (except the last split) read one extra line in
// next() method.
if (start != 0) {
  start += in.readLine(new Text(), 0, maxBytesToConsume(start));
}
this.pos = start;

de esto creo que hadoop leerá una línea adicional para cada división (al final de la división actual, lea la siguiente línea en la siguiente división), y si no se divide primero, la primera línea se descartará. para que no se pierda ningún registro de línea e incompleto




Por lo que he entendido, cuando FileSplit se inicializa para el primer bloque, se llama al constructor predeterminado. Por lo tanto, los valores para inicio y duración son cero inicialmente. Al final del procesamiento del primer bloque, si la última línea está incompleta, entonces el valor de la longitud será mayor que la longitud de la división y también leerá la primera línea del bloque siguiente. Debido a esto, el valor de inicio para el primer bloque será mayor que cero y bajo esta condición, el LineRecordReader omitirá la primera línea del segundo bloque. (Ver source )

En caso de que se complete la última línea del primer bloque, entonces el valor de la longitud será igual a la longitud del primer bloque y el valor del inicio para el segundo bloque será cero. En ese caso, el LineRecordReader no omitirá la primera línea y leerá el segundo bloque desde el principio.

¿Tiene sentido?




Links