2012-01-16 23 views
5

Soy nuevo en Hadoop y estoy tratando de descubrir cómo funciona. En cuanto a un ejercicio, debería implementar algo similar al WordCount-Example. La tarea es leer en varios archivos, hacer el WordCount y escribir un archivo de salida para cada archivo de entrada. Hadoop usa un combinador y mezcla la salida de la parte del mapa como una entrada para el reductor, luego escribe un archivo de salida (supongo para cada instancia que se está ejecutando). Me preguntaba si es posible escribir un archivo de salida para cada archivo de entrada (así que guarde las palabras de inputfile1 y escriba el resultado en outputfile1 y así sucesivamente). ¿Es posible sobrescribir el Combinador de clase o hay otra solución para esto (no estoy seguro de si esto debería resolverse incluso en una Hadoop-Tarea, pero este es el ejercicio).Hadoop MapReduce - un archivo de salida para cada entrada

Gracias ...

Respuesta

1

map.input.file parámetro de entorno tiene el nombre de archivo que está procesando el asignador. Obtenga este valor en el mapeador y utilícelo como la clave de salida para el mapeador y luego todas las k/v de un solo archivo para ir a un reductor.

El código en el asignador. Por cierto, estoy usando la antigua API MR

@Override 
public void configure(JobConf conf) { 
    this.conf = conf; 
} 

@Override. 
public void map(................) throws IOException { 

     String filename = conf.get("map.input.file"); 
     output.collect(new Text(filename), value); 
} 

y el uso MultipleOutputFormat, esto permite escribir varios archivos de salida para el trabajo. Los nombres de archivo se pueden derivar de las claves y valores de salida.

+0

gracias, creo que es la mejor idea. Tal vez usaré la antigua API porque parece más fácil de manejar, pero primero echaré un vistazo a 0.20 – spooky

0

datos 'trozos' de Hadoop en bloques de un tamaño configurado. El valor predeterminado es 64 MB bloques. Puede ver dónde esto causa problemas para su enfoque; Cada mapeador puede obtener solo una parte de un archivo. Si el archivo tiene menos de 64 MB (o el valor que se configure), cada asignador obtendrá solo 1 archivo.

He tenido una restricción muy similar; Necesitaba un conjunto de archivos (salida del reductor anterior en la cadena) para ser procesados ​​por un solo mapeador. Uso el hecho de < 64MB en mi solución El objetivo principal de mi solución es que lo configuré para proporcionarle al mapeador el nombre de archivo que necesitaba para procesarlo, y el mapeador interno lo cargó/leyó el archivo. Esto permite que un solo mapeador procese un archivo completo. No se trata de un proceso distribuido del archivo, pero con la restricción de "No quiero que se distribuyan archivos individuales", funciona. :)

Tuve el proceso que inició mi MR escribir los nombres de archivo de los archivos para procesar en archivos individuales. Donde esos archivos fueron escritos fue el directorio de entrada. Como cada archivo es < 64MB, se generará un único asignador para cada archivo. El proceso map se llamará exactamente una vez (ya que solo hay 1 entrada en el archivo).
Luego tomo el valor pasado al mapeador y puedo abrir el archivo y hacer cualquier asignación que necesite hacer. Dado que hadoop intenta ser inteligente acerca de cómo se correlacionan/reducen los procesos, puede ser necesario especificar el número de reductores que se utilizarán para que cada asignador se dirija a un solo reductor. Esto se puede establecer a través de la configuración mapred.reduce.tasks. Lo hago a través de job.setNumReduceTasks("mapred.reduce.tasks",[NUMBER OF FILES HERE]);

Mi proceso tenía algunos requisitos/restricciones adicionales que pueden haber hecho atractiva esta solución específica; pero para un ejemplo de 1: en 1: afuera; Lo he hecho, y los fundamentos están establecidos arriba.

HTH

+0

Gracias por la entrada. Con setNumReduceTasks obtengo tantos archivos de salida como necesito. Sin embargo, la entrada para los reductores todavía se mezcla/baraja. Revisé el resultado de mi asignador y parece que un asignador está procesando dos archivos (pero este no debería ser el problema). Pero también los resultados de los mapeadores que solo procesan un archivo se mezclan con los resultados de los otros mapeadores.¿Puedo evitar que Hadoop haga esto (mezclar/combinar? ¿Tal vez configurar el combinerclass?) ¿Acaba de obtener todos los nombres de archivos y pasarlos al asignador? ¿O me estoy perdiendo algo? Tal vez otro valor de confianza para establecerse? – spooky

+0

Para forzar un reductor específico, haga que cada asignador use una tecla específica al escribir la salida. Las mismas claves irán al mismo asignador. Puede pasar un valor diferente en la configuración para cada trabajo y luego usar ese valor como la clave. Eso daría como resultado que la salida de cada mapeador vaya a un solo reductor (en mi experiencia). – Nija

+1

Pasar los nombres de los archivos a un asignador para que un solo mapeador procese un archivo no es el enfoque eficiente. No hay localización de datos y habrá datos más aleatorios. Una forma de resolver esto es agrupar los archivos dependientes en 1 (gz, tar) y devolver falso del método FileInputFormat # isSplitable. –

Cuestiones relacionadas