2011-11-15 28 views
7

Tengo un archivo en el que un conjunto de cuatro líneas representa un registro.Hadoop leer varias líneas a la vez

por ejemplo, cuatro primeras líneas representan grabar1, próximo cuatro representan ficha 2 y así sucesivamente ..

Como puedo garantizar de entrada Mapper estas cuatro líneas a la vez?

Además, quiero que la división de archivos en Hadoop suceda en el límite de registros (número de línea debe ser un múltiplo de cuatro), por lo que los registros no consiguen extenderse a lo largo de múltiples archivos divididos ..

¿Cómo puede ser esto estar hecho?

Respuesta

11

algunos enfoques, algunos más sucio que otros:


la manera correcta

Puede que tenga que definir su propio RecordReader, InputSplit y InputFormat. Dependiendo de lo que intente hacer exactamente, podrá reutilizar algunos de los tres anteriores. Probablemente tendrá que escribir su propio RecordReader para definir el par clave/valor y probablemente tendrá que escribir su propio InputSplit para ayudar a definir el límite.


Otra manera correcta, lo cual puede no ser posible

La tarea anterior es bastante desalentador. ¿Tienes algún control sobre tu conjunto de datos? ¿Puedes preprocesarlo de alguna manera (ya sea cuando está entrando o en reposo)? Si es así, debería considerar tratar de transformar su conjunto de datos en algo que sea más fácil de leer de manera inmediata en Hadoop.

Algo así como:

ALine1 
ALine2   ALine1;Aline2;Aline3;Aline4 
ALine3 
ALine4  -> 
BLine1 
BLine2   BLine1;Bline2;Bline3;Bline4; 
BLine3 
BLine4 

abajo y sucio

¿Tiene algún control sobre los tamaños de archivo de los datos? Si divide manualmente sus datos en el límite del bloque, puede forzar a Hadoop a que no le importen los registros que abarcan divisiones. Por ejemplo, si su tamaño de bloque es de 64 MB, escriba sus archivos en fragmentos de 60 MB.

Sin preocuparse por las divisiones de entrada, podría hacer algo sucio: en su función de mapa, agregue su nueva pareja clave/valor en un objeto de lista. Si el objeto de la lista tiene 4 elementos, haga el procesamiento, emita algo y limpie la lista. De lo contrario, no emita nada y continúe sin hacer nada.

La razón por la que tiene que dividir manualmente los datos es que no se le garantizará que se otorgue un registro completo de 4 filas a la misma tarea de mapa.

+0

Gracias por su respuesta, yo estaba pensando en el segundo enfoque que usted sugiere, pero no es que también plagadas con el mismo problema? ¿Cómo leo cuatro líneas a la vez para anexarlas juntas y crear una sola línea? – Gitmo

+0

Podrías escribir algo en Perl o Python que podría hacer el truco. Eso es lo que tenía en mente. –

+0

Utilice [SequenceFile] (http://hadoop.apache.org/common/docs/current/api/org/apache/hadoop/io/SequenceFile.html) con compresión para un mejor rendimiento si se realiza el procesamiento previo del archivo . –

3

Otra forma (fácil pero puede no ser eficiente en algunos casos) es implementar el FileInputFormat#isSplitable(). Entonces los archivos de entrada no se dividen y se procesan uno por mapa.

import org.apache.hadoop.fs.*; 
import org.apache.hadoop.mapred.TextInputFormat; 
public class NonSplittableTextInputFormat extends TextInputFormat { 
    @Override 
    protected boolean isSplitable(FileSystem fs, Path file) { 
     return false; 
    } 
} 

Y como orangeoctopus dicho

In your map function, add your new key/value pair into a list object. If the list object has 4 items in it, do processing, emit something, then clean out the list. Otherwise, don't emit anything and move on without doing anything.

Esto tiene algo de sobrecarga por las siguientes razones

  • Tiempo para procesar el archivo más grande arrastra el momento de finalización del trabajo.
  • Se pueden transferir muchos datos entre los nodos de datos.
  • El clúster no se utiliza correctamente, ya que # de mapas = # de archivos.

** El código anterior es de Hadoop : The Definitive Guide

+0

¡Gracias! Pero estoy usando la API nueva. – Gitmo

+0

Esta idea suena prometedora. ¿Qué le parece usar NLinesInputFormat para especificar el número de líneas para cada asignador? De esta forma, no dependerá del archivo más grande. El problema es que estoy usando Hadoop 0.20 que no tiene esto implementado. ¿Alguna idea? – Gitmo

+0

En 0.20 NLineInputFormat no está implementado en la nueva API. Puede intentar portar la nueva API NLinesInputFormat desde alguna otra versión en 0.20. No debería ser tan difícil y también estarías aprendiendo a compilar y construir un jar de Hadoop. –

Cuestiones relacionadas