mapreduce en hadoop
DESCRIPTION
Uso de MapReduce en Hadoop v2. Algoritmos MapReduce.TRANSCRIPT
MapReduce en Hadoop
Tomás Fernández Pena
Máster en Computación de Altas Prestaciones
Universidade de Santiago de Compostela
Computación en Sistemas Distribuidos
Material bajo licencia Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)citius.usc.es
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Índice
1 Java MapReduce en Hadoop
2 Serialización y Entrada/Salida
Entrada/salida con ficheros de texto
Compresión
Entrada salida/binaria
Serialización con Avro
3 Tareas MapReduce
Algoritmos: encadenamiento, ordenación, fuentes múltiples
Localización de dependencias
Contadores
Ejemplo avanzado
4 Otros aspectos
5 Alternativas a Java
MapReduce en Hadoop, CSD
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Índice
1 Java MapReduce en Hadoop
2 Serialización y Entrada/Salida
Entrada/salida con ficheros de texto
Compresión
Entrada salida/binaria
Serialización con Avro
3 Tareas MapReduce
Algoritmos: encadenamiento, ordenación, fuentes múltiples
Localización de dependencias
Contadores
Ejemplo avanzado
4 Otros aspectos
5 Alternativas a Java
MapReduce en Hadoop, CSD
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Java MapReduce en Hadoop
Un programa MapReduce en Java debe definir 3 clases:
1. Una clase mapper
2. Una clase reducer
3. Una clase principal, con el método main
Pueden crearse
como tres clases públicas separadas
como una sola, con el método main, y clases internas static para
mapper y reducer
MapReduce en Hadoop, CSD 1/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Nueva y vieja API
Los programas pueden usar la nueva API (recomendado) o la antigua
Ambas APIs son incompatibles
Utilizaremos siempre la API nueva
Disponible desde Hadoop 0.20.0
Definida en el paquete org.apache.hadoop.mapreduce
Algunas librerías presentes en la API vieja no han sido portadas
API vieja (desaconsejada)
Definida en el paquete org.apache.hadoop.mapred
MapReduce en Hadoop, CSD 2/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount Mapper
public class WordCountMapper
extends Mapper<LongWritable , Text , Text , IntWritable> {
@Override
public void map(LongWritable key , Text value , Context ctxt )
throws IOException , InterruptedException {
Matcher matcher = pat .matcher(value . toString ( ) ) ;
while (matcher . f ind ( ) ) {
word. set (matcher .group ( ) . toLowerCase ( ) ) ;
ctxt . write (word, one) ;
}
}
private Text word = new Text ( ) ;
private f ina l stat ic IntWritable one = new IntWritable (1) ;
private Pattern pat =
Pattern . compile ( " \ \ b[a−zA−Z\ \u00C0−\\uFFFF]+\\b" ) ;
}
MapReduce en Hadoop, CSD 3/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount Mapper
Extiende la clase
Mapper<KEYIN,VALUEIN,KEYOUT,VALUEOUT>
Debe sobrescribir el método
map(KEYIN key, VALUEIN value, Mapper.Contextcontext)
Usa una instancia de Context en la que escribe los pares
clave/valor de salida
Debe utilizar tipos de datos que implementen la interfazWritable (como LongWritable o Text)
. optimizados para serialización
Otros métodos que se pueden sobrescribir:
. setup(Context context) Llamado una vez al comienzo de la
tarea
. cleanup(Context context) Llamado una vez al final de la
tarea
MapReduce en Hadoop, CSD 4/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount Reducer
public class WordCountReducer
extends Reducer<Text , IntWritable , Text , IntWritable> {
@Override
public void reduce(Text key , Iterable<IntWritable> values ,
Context ctxt ) throws IOException , InterruptedException {
int sum = 0;
for ( IntWritable value : values ) {
sum += value . get ( ) ;
}
ctxt . write (key , new IntWritable (sum) ) ;
}
}
MapReduce en Hadoop, CSD 5/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount Reducer
Extiende la clase
Reducer<KEYIN,VALUEIN,KEYOUT,VALUEOUT>
Debe sobrescribir el método
reduce(KEYIN key, Iterable<VALUEIN> values,Reducer.Context context)
Usa una instancia de Context en la que escribe los pares
clave/valor de salida
Debe utilizar tipos de datos que implementen la interfazWritable (como LongWritable o Text)
. optimizados para serialización
Otros métodos que se pueden sobrescribir:
. setup(Context context) Llamado una vez al comienzo de la
tarea
. cleanup(Context context) Llamado una vez al final de la
tarea
MapReduce en Hadoop, CSD 6/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount Driver (I)
public class WordCountDriver
extends Configured implements Tool {
public int run( String [ ] arg0) throws Exception {
i f (arg0 . length != 2) {
System. err . pr int f ( "Usar : %s [ops] <entrada> <salida >\n" ,
getClass ( ) .getSimpleName() ) ;
ToolRunner .printGenericCommandUsage(System. err ) ;
return −1;
}
Configuration conf = getConf ( ) ;
Job job = Job . getInstance (conf ) ;
job .setJobName( "Word Count" ) ;
job . setJarByClass ( getClass ( ) ) ;
FileInputFormat . addInputPath( job , new Path(arg0[0]) ) ;
FileOutputFormat . setOutputPath ( job , new Path(arg0[1]) ) ;
MapReduce en Hadoop, CSD 7/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount Driver (II)
job . setOutputKeyClass (Text . class ) ;
job . setOutputValueClass ( IntWritable . class ) ;
job .setNumReduceTasks(4) ;
job . setMapperClass(WordCountMapper. class ) ;
job . setCombinerClass (WordCountReducer . class ) ;
job . setReducerClass (WordCountReducer . class ) ;
return ( job . waitForCompletion ( true ) ? 0 : −1);
}
public stat ic void main( String [ ] args ) throws Exception {
int exitCode = ToolRunner . run(new WordCountDriver ( ) , args ) ;
System. exit (exitCode) ;
}
}
MapReduce en Hadoop, CSD 8/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount Driver
Clase Configured: permite acceder a la configuración delsistema
. Método Configuration getConf(): devuelve la
configuración actual
Clase Configuration: proporciona acceso a la configuración
Clase Job: permite configurar, enviar y controlar la ejecución de un
trabajo
Clase FileInputFormat<K,V>: describe los ficheros de
entrada en un trabajo MapReduce
Clase FileOutputFormat<K,V>: describe los ficheros de
entrada en un trabajo MapReduce
MapReduce en Hadoop, CSD 9/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount Driver
Interfaz Tool: interfaz estándar para aplicaciones MapReduce,
soporta el manejo de opciones en línea de comandos
Clase ToolRunner: ejecuta clases que implementan la interfaz
Tool
Clase Path: identifica a un fichero o directorio en el FileSystem
MapReduce en Hadoop, CSD 10/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Número de Reducers
Tener un único reducer no suele ser una buena idea
Más reducers: más paralelismo
Más reducers: startup más lento, más overhead de disco y red
Difícil determinar el número óptimo
Ver wiki.apache.org/hadoop/HowManyMapsAndReduces
Varios reducers producen varios ficheros de salida:
Se pueden unir con hdfs dfs -getmerge
MapReduce en Hadoop, CSD 11/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Compilación y ejecución
Preferiblemente, crear un jar con todas las clases y ejecutarlo con:
yarn jar fichero.jar [opciones]
Para gestionar las aplicaciones, utilizad:
. en general, la opción application del comando yarn (yarnapplication -help para ver las opciones)
. para trabajos MapReduce, la opción job del comando mapred(mapred job -help para ver las opciones)
Más información en
. hadoop.apache.org/docs/current/hadoop-yarn/hadoop-yarn-
site/YarnCommands.html
. hadoop.apache.org/docs/current/hadoop-mapreduce-client/hadoop-
mapreduce-client-core/MapredCommands.html
MapReduce en Hadoop, CSD 12/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Índice
1 Java MapReduce en Hadoop
2 Serialización y Entrada/Salida
Entrada/salida con ficheros de texto
Compresión
Entrada salida/binaria
Serialización con Avro
3 Tareas MapReduce
Algoritmos: encadenamiento, ordenación, fuentes múltiples
Localización de dependencias
Contadores
Ejemplo avanzado
4 Otros aspectos
5 Alternativas a Java
MapReduce en Hadoop, CSD
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Writables
Formato de serialización de objetos de Hadoop
Transforma objetos en un flujo de bytes para transmisión o
almacenamiento
Gran número de clases que implementan el interfaz Writable:
Objetos primitivos: BooleanWritable, ByteWritable,
IntWritable, LongWritable, FloatWritable,
DoubleWritable, Text (cadenas UTF-8)
Objetos primitivos de longitud variable: VIntWritable,
VLongWritable
Colecciones: ArrayWritable, ArrayPrimitiveWritable,
TwoDArrayWritable, MapWritable,
SortedMapWritable
Otros: NullWritable, BytesWritable, ObjectWritable,
GenericWritable,
MapReduce en Hadoop, CSD 13/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Writables a medida
Es posible implementar writables a medida
Implementar la interfaz Writable. Implementar los métodos write(DataOutput out) y
readFields(DataInput in)
Un objeto que se quiera usar como clave debe implementar
WritableComparable
MapReduce en Hadoop, CSD 14/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Ejemplo de writable
public class MyWritable implements Writable {
/ / Incluye un entero y un long
private IntWritable counter ;
private LongWritable timestamp;
public void write (DataOutput out ) throws IOException {
counter . write (out ) ;
timestamp. write (out ) ;
}
public void readFields (DataInput in ) throws IOException {
counter . readFields ( in ) ;
timestamp. readFields ( in ) ;
}
public stat ic MyWritable read(DataInput in ) throws IOException {
MyWritable w = new MyWritable ( ) ;
w. readFields ( in ) ;
return w;
}
}
MapReduce en Hadoop, CSD 15/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Clase abstracta FileInputFormat<K,V>
Define métodos para añadir uno o varios paths de entrada al trabajoaddInputPath(Job job, Path path), addInputPaths(Jobjob, String commaSeparatedPaths)
Clase base para diferentes formatos de entrada concretos
El formato a usar se especifica mediante el método
setInputFormatClass del Job, por ejemplo:
job.setInputFormatClass(TextInputFormat.class)
MapReduce en Hadoop, CSD 16/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Formatos de entrada
TextInputFormat: formato por defecto para ficheros de texto
KeyValueTextInputFormat: ficheros de texto con estructura
clave/valor
NLineInputFormat: permite que los mappers reciban un
número fijo de líneas de entrada
SequenceFileInputFormat: secuencias de datos binarios
clave/valor
CombineFileInputFormat: Permite empaquetar varios
ficheros pequeños en un split de entrada de un tamaño
determinado
FixedLengthInputFormat: Usado para leer ficheros con
registros de longitud fija
MapReduce en Hadoop, CSD 17/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Formatos de entrada
TextInputFormat:
. Formato por defecto
. Cada mapper recibe un trozo (split) del fichero y lo procesa línea a
línea
. Como clave, toma el offset en bytes en el fichero desde el comienzo
de la línea (LongWritable)
. Como valor, toma toda la línea
KeyValueTextInputFormat:
. Igual que el anterior, pero separa cada línea en clave/valor
. Usa tabulado como separador por defecto
. Para cambiar, modificar en el objeto Configuration la propiedad
mapreduce.input.keyvaluelinerecordreader.key.value.separator
Nota: en la API vieja es key.value.separator.in.input.line
MapReduce en Hadoop, CSD 18/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Salida de ficheros
Similar a la entrada: clase abstracta FileOutputFormat<K,V>
Clase base para diversos formatos de salida concretos
. TextOutputFormat: formato por defecto para ficheros de texto
- Escribe líneas de texto en formato clave/valor separados por un
tabulado
- Carácter de separación modificable:
mapreduce.output.textoutputformat.separatorAPI vieja mapred.textoutputformat.separator
. SequenceFileOutputFormat: secuencias de datos binarios
clave/valor
. MapFileOutputFormat: Un formato de salida que escribe
MapFiles
El formato a usar se especifica mediante el método
setOutputFormatClass del Job
MapReduce en Hadoop, CSD 19/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Compresión
Como vimos en el WordCount, Hadoop lee directamente ficheros
comprimidos:
Los ficheros se descomprimen automáticamente, usando la
terminación del fichero para determinar que codec usar
Formato Java/Nativo Splittable Codec
zlib/DEFLATE Sí/Sí No DefaultCodecgzip Sí/Sí No GzipCodecbzip2 Sí/Sí Sí BZip2CodecLZO No/Sí No (Sí con preproceso) LzopCodecLZ4 No/Sí No Lz4CodecSnappy No/Sí No SnappyCodec
MapReduce en Hadoop, CSD 20/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Compresión
Fuente: Kamat, G., Singh, S., “Compression Options in Hadoop - A Tale of Tradeoffs”, Hadoop Summit (San Jose), June 27, 2013
MapReduce en Hadoop, CSD 21/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Compresión
Recomendaciones:
Usar contenedores binarios como Sequence File o Avro datafile
(soportan compresión y splitting)
Usar formatos splittables
Dividir los ficheros en trozos y comprimirlos por separado (cada
trozo comprimido debería ocupar un bloque HDFS)
No usar compresión
MapReduce en Hadoop, CSD 22/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Entrada salida/binaria
Hadoop puede usar ficheros binarios de entrada/salida usando la clase
SequenceFile
Estructura de datos persistente para pares binarios clave/valor
Para crear un SequenceFile:
IntWritable key = new IntWritable (3) ;
Text value = new Text ( " tres " ) ;
Path path = new Path( ur i ) ;
writer = SequenceFile . createWriter ( conf , SequenceFile . Writer . f i l e (path) ,
SequenceFile . Writer . keyClass (key . getClass ( ) ) ,
SequenceFile . Writer . valueClass (value . getClass ( ) ) ) ;
writer .append(key , value ) ;
IOUti ls . closeStream( writer ) ;
Para leer el fichero, en el programa crear un SequenceFile.Readery usar next()
MapReduce en Hadoop, CSD 23/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Serialización con Avro
Apache Avro es un sistema de serialización independiente del lenguaje
Formato procesable por varios lenguajes: C, C++, C#, Java, PHP,
Python y Ruby
Puede substituir a los Writables
Proporciona clases para facilitar crear programas MapReduce que
usen datos Avro (usa la API vieja)
Tipos de datos en Avro
Primitivos: null, boolean, int, long, float, double, string
Complejos: array, map, record, enum, fixed, union
MapReduce en Hadoop, CSD 24/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Serialización con Avro
Apache Avro es un sistema de serialización independiente del lenguaje
Formato procesable por varios lenguajes: C, C++, C#, Java, PHP,
Python y Ruby
Puede substituir a los Writables
Proporciona clases para facilitar crear programas MapReduce que
usen datos Avro (usa la API vieja)
Tipos de datos en Avro
Primitivos: null, boolean, int, long, float, double, string
Complejos: array, map, record, enum, fixed, union
MapReduce en Hadoop, CSD 24/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Esquemas Avro
Los esquemas Avro permiten construir estructuras de datos complejas
Se escriben habitualmente en formato JSON
Se guardan en un fichero con terminación .avsc
En Java podemos usar dos APIs para manejarlos:
API genérica:
. Mapping dinámico
. Puede usarse aunque el esquema no sea conocido hasta runtime
API específica
. A partir del esquema, se genera código que lo representa
. Necesita conocer el esquema en tiempo de compilación
MapReduce en Hadoop, CSD 25/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Esquemas Avro
Ejemplo de esquema
{
"namespace" : "cursohadoop . creaavrofi le " ,
"type" : "record" ,
"name" : "PatentData" ,
"doc" : "Dos enteros y un string " ,
" f ie lds " : [
{"name" : "patente" , "type" : " long"},
{"name" : "anho" , "type" : " int "},
{"name" : "pais " , "type" : " string "}
]
}
MapReduce en Hadoop, CSD 26/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Avro Datafiles
Contenedores de objetos similares a los SequenceFile
Crear un Avro DataFile con la API genérica
Schema. Parser parser = new Schema. Parser ( ) ;
Schema schema =
parser . parse( getClass ( ) . getResourceAsStream( "PatentData . avsc" ) ) ;
FileSystem fsout = FileSystem . get (URI . create (out ) , conf ) ;
OutputStream os = fsout . create (new Path(out ) ) ;
DatumWriter<GenericRecord> writer = new
GenericDatumWriter<GenericRecord>(schema) ;
DataFileWriter<GenericRecord> dataFileWriter = new
DataFileWriter<GenericRecord>(writer ) ;
dataFileWriter . create (schema, os) ;
GenericRecord patente = new GenericData .Record(schema) ;
patente . put ( "patente" , 12345678);
patente . put ( "anho" , 2013) ;
patente . put ( "pais" , "ES" ) ;
dataFileWriter .append(patente ) ;
MapReduce en Hadoop, CSD 27/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Ejemplo: WordCount con salida Avro
Cambios en el WordCountDriver para usar salida Avro:
job . setInputFormatClass (TextInputFormat . class ) ;
job . setOutputFormatClass (AvroKeyValueOutputFormat . class ) ;
job . setMapOutputKeyClass(Text . class ) ;
job . setMapOutputValueClass( IntWritable . class ) ;
AvroJob .setOutputKeySchema( job , Schema. create (Type.STRING) ) ;
AvroJob . setOutputValueSchema( job , Schema. create (Type. INT) ) ;
Eliminar las definiciones job.setOutputKeyClass(Text.class) y
job.setOutputValueClass(IntWritable.class), y no uséis Combiner.
MapReduce en Hadoop, CSD 28/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Ejemplo: WordCount con salida Avro
Cambios en el WordCountReducer para usar salida Avro:
public class AvroWordCountReducer extends Reducer<Text , IntWritable ,
AvroKey<CharSequence>, AvroValue<Integer>> {
public void reduce(Text key , Iterable<IntWritable> values , Context ctxt )
throws IOException , InterruptedException {
int sum = 0;
for ( IntWritable value : values ) {
sum += value . get ( ) ;
}
ctxt . write (new AvroKey<CharSequence>(key . toString ( ) ) , new
AvroValue<Integer>(sum) ) ;
}
}
MapReduce en Hadoop, CSD 29/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Ejecutar el WordCount salida Avro en el cluster
Dependencias en el pom.xml
hadoop-core (2.5.1), avro (1.7.4 [jar]), avro-mapred (1.7.5,
[jar,hadoop2])
Definición del classpath:
Definir HADOOP_CLASSPATH (export HADOOP_CLASSPATH)
para que incluya los jars de avro, avro-mapred y paranamer
(separados por “:”)
Definir una variable LIBJARS que incluya los mismos jars, pero
separados por “,”
Esos jars los encontramos en $HOME/.m2/repository bajo
org/apache/avro/avro/1.7.4 y
org/apache/avro/avro-mapred/1.7.4
Ejecución:
$ yarn jar wordcountavro*.jar -libjars $LIBJARS libros
librosoutavro
MapReduce en Hadoop, CSD 30/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Verificar la salida Avro
La salida del código anterior es uno o varios ficheros .avro
Para leerlo, podemos usar las avro-tools
Descargar el fichero avro-tools-*.jar desde avro.apache.org
(la versión estable)
Ejecutar:
$ java -jar avro-tools-*.jar tojson fichero.avro
MapReduce en Hadoop, CSD 31/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Índice
1 Java MapReduce en Hadoop
2 Serialización y Entrada/Salida
Entrada/salida con ficheros de texto
Compresión
Entrada salida/binaria
Serialización con Avro
3 Tareas MapReduce
Algoritmos: encadenamiento, ordenación, fuentes múltiples
Localización de dependencias
Contadores
Ejemplo avanzado
4 Otros aspectos
5 Alternativas a Java
MapReduce en Hadoop, CSD
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Encadenamiento de trabajos MapReduce
Es posible encadenar trabajos MapReduce
Basta con definir varios jobs y lanzarlos unos detrás de otros
La salida a disco de un job es leída por el siguiente
Alternativa
Usar las clases ChainMapper y ChainReducer
Permiten encadenar varios mappers seguidos de un reducer y un
mapper adicional ([MAP+ / REDUCE MAP*])
Reduce los accesos a disco
Para workflows complejos, se puede usar Apache Oozie o Cascading
MapReduce en Hadoop, CSD 32/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Ordenación
Por defecto, MapReduce ordena los registros de entrada por las claves
Uso para hacer ordenamientos de datos
Problema si usamos múltiples reducers
Es posible usar hdfs dfs -getmerge para unirlos
Lento con ficheros grandes
MapReduce en Hadoop, CSD 33/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Total Sort
Producir un conjunto de ficheros ordenados, que concatenados, formen
un fichero ordenado global
Usar como particionador un objeto de la clase
TotalOrderPartitioner
Efectúa una ordenación total leyendo marcas de separación de una
fuente externa
Usar un InputSampler para obtener las muestras
MapReduce en Hadoop, CSD 34/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Secondary Sort
La ordenación se hace sólo por la clave:
El orden en que aparecen los valores no está fijado
Es posible imponer un orden en el que aparecen los valores:
Hacer que la clave esté compuesta por la clave natural y el valor
natural (objeto WritableComparable)
El comparador de ordenación debe ordenar usando esa clave
compuesta
El particionador debe considerar sólo la clave natural
El comparador de agrupamiento usa una u otra según el caso
MapReduce en Hadoop, CSD 35/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Secondary SortEjemplo de clave compuesta
Clave compuesta
Clave Valor{ {{
Particionar
Ordenar/Agrupar
Se ordena por la clave compuesta [clave, valor](job.setSortComparatorClass)
Se particiona por clave (job.setPartitionerClass,
garantiza que las mismas claves van al mismo reducer)
Se agrupa por la clave o la clave compuesta [clave, valor]dependiendo del problema
(job.setGroupingComparatorClass)
MapReduce en Hadoop, CSD 36/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Joins de datos de diferentes fuentes
Hacer uniones de datos de diferentes fuentes es complejo en Hadoop
Preferible usar lenguajes de alto nivel como Pig o Hive
En Hadoop hay varias soluciones:
Si un conjunto de datos es grande y el otro pequeño, se puede
replicar el pequeño en todos los nodos usando Distributed Cache
Map-Side joins: el join se realiza antes de llegar a la función map
. Los conjuntos de datos deben dividirse en el mismo número de
particiones y estar ordenados por la clave de unión
Reduce-side joins: el join se realiza en el reducer
. El mapper etiqueta cada dato con su fuente y usa la clave de unión
como clave de salida
MapReduce en Hadoop, CSD 37/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Localización de dependencias
Mecanismo para copiar recursos (LocalResources) a los nodos del cluster
Hadoop (DistributedCache en Hadoop v1)
Los recursos (ficheros, archivos, librerías) se copian a todos los
nodos una vez por trabajo
Las aplicaciones pueden acceder directamente a estos recursos
Tipos de LocalResources:
. FILE: Ficheros normales
. ARCHIVE: Ficheros comprimidos (jar, tar, tar,gz, zip) que
descomprime el NodeManager
. PATTERN: Híbrido de ARCHIVE y FILE (se mantiene el fichero y se
descomprime parte)
Visibilidad de los LocalResources
. PUBLIC: accesibles por todos los usuarios
. PRIVATE: compartidos por aplicaciones del mismo usuario en el nodo
. APPLICATION: compartidos entre containers de la misma aplicación
MapReduce en Hadoop, CSD 38/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Uso en línea de comandos
Si el código usa GenericOptionParser (o ToolRunner), los
ficheros a copiar se indican como parámetro:
-files + lista separada por comas de URIs de los ficheros
-archives + ficheros comprimidos (archivos)
-libjars + JARS para añadir al CLASSPATH
Ejemplo:
hadoop jar mr.jar -files ~/fichero in out
MapReduce en Hadoop, CSD 39/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Uso desde la aplicación
Métodos definidos en Job
addCacheFile(URI uri): añade un fichero a la cache
addCacheArchive(URI uri): añade un archivo a la cache
addFileToClassPath(Path file): añade un fichero al
CLASSPATH
addArchiveToClassPath(Path file): añade un archivo
al CLASSPATH
URI[] getCacheFiles(): obtiene los ficheros en la cache
URI[] getCacheArchives(): obtiene los archivos en la
cache
MapReduce en Hadoop, CSD 40/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Contadores
Hadoop incorpora contadores para obtener datos del trabajo:
Contadores internos: informan sobre el comportamiento de la
ejecución
Contadores definidos por el usuario (interfaz Counter)
. Permiten obtener información adicional sobre las tareas
. Definidos mediante Java enums, que permiten agrupar contadores
relacionados
. Se accede a ellos mediante el método getCounter() del
MapContext o el ReduceContext. Se modifican mediante los métodos del interfaz Counter
MapReduce en Hadoop, CSD 41/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount2 Mapper (I)
public class WordCountMapper2 extends
Mapper<LongWritable , Text , Text , IntWritable> {
stat ic enum CountersEnum {
PALABRAS_INCLUIDAS
}
@Override
public void setup(Context ctxt ) throws IOException ,
InterruptedException {
conf = ctxt . getConfiguration ( ) ;
caseSensitive = conf . getBoolean( "wordcount . case . sensitive " , true ) ;
i f ( conf . getBoolean( "wordcount . skip . patterns" , false ) ) {
URI [ ] patternsURIs = Job . getInstance (conf ) . getCacheFiles ( ) ;
for (URI patternsURI : patternsURIs ) {
Path patternsPath = new Path( patternsURI . getPath ( ) ) ;
String patternsFileName = patternsPath .getName() . toString ( ) ;
parseSkipFile (patternsFileName) ;
}
}
}
MapReduce en Hadoop, CSD 42/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount2 Mapper (II)@Override
public void map(LongWritable key , Text value , Context ctxt ) throws
IOException , InterruptedException {
String l ine = ( caseSensitive ) ? value . toString ( ) :
value . toString ( ) . toLowerCase ( ) ;
for ( String pattern : patternsToSkip ) {
l ine = l ine . replaceAll ( " \ \ b"+pattern+" \ \ b" , " " ) ;
}
Matcher matcher = pat .matcher( l ine ) ;
while (matcher . f ind ( ) ) {
String token = matcher .group ( ) ;
i f (words . containsKey( token) ) {
int total = words . get ( token) + 1;
words . put ( token , total ) ;
} else {
words . put ( token , 1) ;
}
ctxt . getCounter (CountersEnum.PALABRAS_INCLUIDAS) . increment(1) ;
}
}
MapReduce en Hadoop, CSD 43/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount2 Mapper (III)
@Override
public void cleanup(Context ctxt ) throws
IOException , InterruptedException {
Iterator<Map. Entry<String , Integer>> i t = words . entrySet ( ) . i terator ( ) ;
while ( i t . hasNext ( ) ) {
Map. Entry<String , Integer> entry = i t . next ( ) ;
String sKey = entry .getKey ( ) ;
int total = entry . getValue ( ) . intValue ( ) ;
ctxt . write (new Text (sKey) , new IntWritable ( total ) ) ;
}
}
MapReduce en Hadoop, CSD 44/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount2 Mapper (IV)
private void parseSkipFile ( String fileName) {
try {
f i s = new BufferedReader (new FileReader ( fileName) ) ;
String pattern = nul l ;
while ( ( pattern = f i s . readLine ( ) ) != nul l ) {
patternsToSkip .add( pattern ) ;
}
} catch ( IOException ioe ) {
System. err . pr int ln ( "Excepcion parseando el recurso local ’ " +
Str ingUti ls . stringifyException ( ioe ) ) ;
}
}
private boolean caseSensitive ;
private Set<String> patternsToSkip = new HashSet<String >() ;
private Map<String , Integer> words = new HashMap<String , Integer >() ;
private Pattern pat = Pattern . compile ( " \ \ b[a−zA−Z\ \u00C0−\\uFFFF]+\\b" ) ;
private Configuration conf ;
private BufferedReader f i s ;
}
MapReduce en Hadoop, CSD 45/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount2 Driver (I)
public class WordCountDriver2 extends Configured implements Tool {
public int run( String [ ] args ) throws Exception {
Configuration conf = getConf ( ) ;
Job job = Job . getInstance (conf ) ;
job .setJobName( "Word Count 2" ) ;
job . setJarByClass ( getClass ( ) ) ;
GenericOptionsParser optionParser = new GenericOptionsParser (conf ,
args ) ;
String [ ] remainingArgs = optionParser . getRemainingArgs ( ) ;
i f ( ! ( remainingArgs . length != 2 | | remainingArgs . length != 4) ) {
System. err . pr int f ( "Usar : %s [ops] <entrada> <salida> [−skip
skipPatternFile ] \n" , getClass ( ) .getSimpleName() ) ;
return −2;
}
MapReduce en Hadoop, CSD 46/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount2 Driver (II)
List<String> otherArgs = new ArrayList<String >() ;
for ( int i=0; i < remainingArgs . length ; ++i ) {
i f ( "−skip " . equals ( remainingArgs[ i ] ) ) {
job . addCacheFile (new Path( remainingArgs[++i ] ) . toUri ( ) ) ;
job . getConfiguration ( ) . setBoolean( "wordcount . skip . patterns" ,
true ) ;
} else {
otherArgs .add( remainingArgs[ i ] ) ;
}
}
FileInputFormat . addInputPath( job , new Path(otherArgs . get (0) ) ) ;
FileOutputFormat . setOutputPath ( job , new Path(otherArgs . get (1) ) ) ;
MapReduce en Hadoop, CSD 47/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
WordCount2 Driver (III)
job . setOutputKeyClass (Text . class ) ;
job . setOutputValueClass ( IntWritable . class ) ;
job .setNumReduceTasks(1) ;
job . setMapperClass(WordCountMapper3. class ) ;
/ /Usa in−mapper combiner
job . setReducerClass (WordCountReducer3. class ) ;
return ( job . waitForCompletion ( true ) ? 0 : −1);
}
public stat ic void main( String [ ] args ) throws Exception {
int exitCode = ToolRunner . run(new WordCountDriver3 ( ) , args ) ;
System. exit (exitCode) ;
}
}
Ejemplo de ejecución:
yarn -jar wc2.jar \-Dwordcount.case.sensitive=true indir outdir \-skip skipfile.txt
MapReduce en Hadoop, CSD 48/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Índice
1 Java MapReduce en Hadoop
2 Serialización y Entrada/Salida
Entrada/salida con ficheros de texto
Compresión
Entrada salida/binaria
Serialización con Avro
3 Tareas MapReduce
Algoritmos: encadenamiento, ordenación, fuentes múltiples
Localización de dependencias
Contadores
Ejemplo avanzado
4 Otros aspectos
5 Alternativas a Java
MapReduce en Hadoop, CSD
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Reuso de las JVM
Por defecto, cada tarea Hadoop se ejecuta en su propia JVM
Mejora el aislamiento entre tareas
Puede suponer un sobrecosto en tareas pequeñas
Es posible reusar las JVMs
Varias tareas (del mismo job) se pueden ejecutar secuencialmente
en una misma JVM
La propiedad que controla el reuso es
mapreduce.job.jvm.numtasks
Su valor por defecto es 1
. Un -1 indica sin límite
MapReduce en Hadoop, CSD 49/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Scheduling
Por defecto, YARN usa Capacity Scheduler con una única cola
(default)
En Hadoop V1 se usa una cola FIFO con prioridades
El scheduler a usar se especifica mediante la variable
yarn.resourcemanager.scheduler.class
En Hadoop V1 propiedad
mapred.jobtracker.taskScheduler
Los scheduler más usados son
Capacity Scheduler
Fair Scheduler
MapReduce en Hadoop, CSD 50/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Capacity Scheduler
Desarrollado por Yahoo, características similares al anterior
Los trabajos se envían a colas, que pueden ser jerárquicas
A cada cola se le reserva una fracción de la capacidad total
En cada cola, los trabajos usan FIFO con prioridades
. Permite simular un cluster MapReduce con FIFO para cada usuario u
organización
Se configura mediante el fichero capacity-scheduler.xml
Más información: hadoop.apache.org/docs/current/hadoop-yarn/hadoop-
yarn-site/CapacityScheduler.html
MapReduce en Hadoop, CSD 51/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Fair Scheduler
Desarrollado por Facebook, con el objetivo de compartir equitativamente
la capacidad del cluster
Intenta proporcionar tiempos de respuesta rápidos para trabajos
cortos y QoS para trabajos en producción
Los trabajos se colocan en pools
Por defecto, cada usuario tiene su propia pool
A cada pool se le garantiza un mínimo de capacidad
. Mínimo numero de map slots, reduce slots, y máximo número de
trabajos simultáneos
La capacidad sobrante se reparte entre los trabajos
Es apropiativo:
. Si un pool no recibe su capacidad mínima, el scheduler puede matar
trabajos que estén usando por encima de su capacidad
Más información: hadoop.apache.org/docs/current/hadoop-yarn/hadoop-
yarn-site/FairScheduler.html
MapReduce en Hadoop, CSD 52/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Ejecución especulativa
Por defecto, la ejecución especulativa está activada
Si una tarea se retrasa, se lanza especulativamente una copia de la
misma
En un cluster muy ocupado, esto puede significar un consumo excesivo
de recursos
Se puede deshabilitar la especulación para mappers o reducers
Más interesante para reducers
. Un reduce duplicado implica volver a obtener las salidas de los
mappers
. Aumento del tráfico de red
Propiedades (booleanas):
mapreduce.map.speculativemapreduce.reduce.speculative
MapReduce en Hadoop, CSD 53/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Tests unitarios con MRUnit
Apache MRUnit es una librería Java que facilita el desarrollo de tests
unitarios para trabajos MapReduce
Clases MapDriver y ReduceDriver
Utilidades que permiten testear el mapper y el reducer
. Se les proporciona pares clave-valor como entrada y se chequea que
la salida sea la esperada
MapReduce en Hadoop, CSD 54/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Índice
1 Java MapReduce en Hadoop
2 Serialización y Entrada/Salida
Entrada/salida con ficheros de texto
Compresión
Entrada salida/binaria
Serialización con Avro
3 Tareas MapReduce
Algoritmos: encadenamiento, ordenación, fuentes múltiples
Localización de dependencias
Contadores
Ejemplo avanzado
4 Otros aspectos
5 Alternativas a Java
MapReduce en Hadoop, CSD
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Alternativas a Java
Hadoop Streaming
API que permite crear códigos map-reduce en otros lenguajes
Utiliza streams Unix como interfaz entre Hadoop y el código
Permite usar cualquier lenguaje que pueda leer de la entrada
estándar y escribir en la salida estándar (Python, Ruby, etc.)
Más información .../HadoopStreaming.html
Hadoop Pipes
Interfaz C++ a Hadoop MapReduce
Usa sockets como canal de comunicación entre el tasktracker y el
proceso C++ que ejecuta el map o el reduce
MapReduce en Hadoop, CSD 55/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Alternativas a Java
Hadoop Streaming
API que permite crear códigos map-reduce en otros lenguajes
Utiliza streams Unix como interfaz entre Hadoop y el código
Permite usar cualquier lenguaje que pueda leer de la entrada
estándar y escribir en la salida estándar (Python, Ruby, etc.)
Más información .../HadoopStreaming.html
Hadoop Pipes
Interfaz C++ a Hadoop MapReduce
Usa sockets como canal de comunicación entre el tasktracker y el
proceso C++ que ejecuta el map o el reduce
MapReduce en Hadoop, CSD 55/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Ejemplo de streaming
WordCount Mapper en Python
#! / usr / bin /env python
#−*− coding : utf−8−*−import re , sys
pattern = re . compile (u ’ \ \ b[a−zA−Z\u00C0−\uFFFF]+\\b ’ )
for l ine in sys . stdin :
line2 = unicode( line , ’ utf−8’ ) . lower ( )
words = pattern . f inda l l ( l ine2 )
for w in words:
print " %s \ t %s" %(w.encode( ’ utf−8’ ) , 1)
MapReduce en Hadoop, CSD 56/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Ejemplo de streaming
WordCount Reducer en Python
#! / usr / bin /env python
#−*− coding : utf−8−*−import sys
( last_key , total ) = (None, 0)
for l ine in sys . stdin :
(key , value ) = l ine . st r ip ( ) . sp l i t ( )
i f last_key and last_key != key:
print " %s \ t %s" %( last_key , total )
( last_key , total ) = (key , int (value ) )
else :
( last_key , total ) = (key , total+int (value ) )
i f last_key :
print " %s \ t %s" %( last_key , total )
MapReduce en Hadoop, CSD 57/58
Java MapReduce en Hadoop Serialización y Entrada/Salida Tareas MapReduce Otros aspectos Alternativas a Java
Ejemplo de streaming
Ejecución del código Python
$ yarn jar \$HADOOP_PREFIX/share/hadoop/tools/lib/hadoop-streaming-*.jar \-input indir -output outdir \-mapper $PWD/WordCountMapper.py \-reducer $PWD/WordCountReducer.py \-file $PWD/WordCountMapper.py \-file $PWD/WordCountReducer.py
Nota: La opción -file sólo se necesita si se ejecuta en un cluster, para
copiar los scripts en los nodos del cluster
MapReduce en Hadoop, CSD 58/58