Get it on Google Play

BigData con Hadoop, framework para procesar grandes cantidades de datos

13-08-2013
 

hadoopDiagramEn esta píldora de formación presentaremos Hadoop, un framework para Java que nos permite implementar el BigData en nuestros proyectos(En realidad no se si hay muchos proyectos en España que puedan utilizar Hadoop).

Hadoop es un framework que nos permite crear aplicaciones que procesen grandes cantidades de datos en batch(Cuando hablamos de grandes cantidades de datos hablamos de Peta-bytes). Hadoop es utilizado por Google o Yahoo para procesar cantidades ingentes de datos, como las webs indexadas por google.

Básicamente Hadoop recibe una entrada de un sistema de ficheros(O carpeta) y aplica sobre él un Job(Trabajo, proceso o como queráis llamarle) programado por nosotros. Después vuelca la salida sobre otro directorio.

Hadoop provee de toda la infraestructura a gran escala para procesar. Esta diseñado para distribuir el proceso entre una gran cantidad de maquinas para repartir la carga de trabajo. Atención! Hadoop no esta diseñado para obtener datos en real-time.

A la hora de diseñar nuestro proceso, deberemos dejar de pensar en clave de SQL. Hadoop aplica los procesos en dos fases:

  • – Primero aplica una función Mapeadora, que por cada línea del fichero de entrada devuelve un listado de pares <clave , valor>. En esta fase debemos prepara la consulta para obtener un listado de pares que después procesaremos para obtener la salida.
  • – Después aplicaremos una función reductora. Esta función recibe como parámetro un listado de todos los valores sobre una determinada clave y devuelve otro listado de pares <clave ,valor>. Este último listado es el que se vuelca sobre la salida.

Puede parecer rebuscado, pero aplicando estas dos funciones podemos sacar reportes de cualquier tipo(Solo es acostumbrarse a pensar en clave de mapear y reducir).

Para ilustrar esto podemos hacer el clásico ejemplo de contar palabras dentro de un libro en formato TXT (Yo me descargué “Moby dick” y “Adventures Of Huckleberry Fin” del proyecto Gutenberg http://www.gutenberg.org/ ).

Antes de empezar tendremos que instalar hadoop en nuestra maquina de desarrollo, yo lo hice descargandome un deb(Para Linux/Ubuntu) desde la página de descargas de Hadoop http://hadoop.apache.org/releases.html . Para comprobar que lo tenemos bien instalado podemos ejecutar ‘hadoop’ en el terminal.

Lo primero será tener instalado Maven con el siguiente fichero POM que nos generara el proyecto(Simplemente ejecutando ‘mvn clean install‘):

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.lostsys.hadoop1</groupId>
  <artifactId>hadoop-examples</artifactId>
  <version>1.0</version>
  <packaging>jar</packaging>

  <name>hadoop1</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-core</artifactId>
            <version>0.20.205.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
  </dependencies>

  <build>
    <plugins>
       <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <version>2.3.1</version>
           <configuration>
               <source>1.5</source>
               <target>1.5</target>
           </configuration>
       </plugin>
    </plugins>
  </build>
</project>

Vemos que el POM solo declara el proyecto, las dependencias de Junit y Hadoop y el compilador.

En nuestro proyecto deberemos declarar la classe con la función Mapeadora:

    public static class MapClass extends MapReduceBase implements Mapper<LongWritable, Text, Text, IntWritable> {
        private Text word = new Text();
        private final static IntWritable one = new IntWritable( 1 );

        public void map( LongWritable key, // Offset into the file
                         Text value,
                         OutputCollector<Text, IntWritable> output,
                         Reporter reporter) throws IOException {

            // Get the value as a String
            String text = value.toString().toLowerCase();

            // Replace all non-characters
            text = text.replaceAll( "'", "" );
            text = text.replaceAll( "[^a-zA-Z]", " " );

            // Iterate over all of the words in the string
            StringTokenizer st = new StringTokenizer( text );
            while( st.hasMoreTokens() ) {
                // Get the next token and set it as the text for our "word" variable
                word.set( st.nextToken() );

                // Output this word as the key and 1 as the value
                output.collect( word, one );
            	}
            }
    }

Después la classe con la función Reductora:

    public static class Reduce extends MapReduceBase implements Reducer<Text, IntWritable, Text, IntWritable> {

        public void reduce( Text key, Iterator<IntWritable> values,
                            OutputCollector<Text, IntWritable> output,
                            Reporter reporter) throws IOException {

            	// Iterate over all of the values (counts of occurrences of this word)
            	int count = 0;
            	while( values.hasNext() ) {
                	// Add the value to our count
                	count += values.next().get();
            		}

            	// Output the word with its count (wrapped in an IntWritable)
            	output.collect( key, new IntWritable( count ) );
        	}
    }

Finalmente la la classe del proyecto(Que extiende de ‘Configures’ y implementa ‘Tool’)

public class HadoopProject1 extends Configured implements Tool {

    public int run(String[] args) throws Exception {
        // Create a configuration
        Configuration conf = getConf();

        // Create a job from the default configuration that will use the WordCount class
        JobConf job = new JobConf( conf, HadoopProject1.class );

        // Define our input path as the first command line argument and our output path as the second
        Path in = new Path( args[0] );
        Path out = new Path( args[1] );

        // Create File Input/Output formats for these paths (in the job)
        FileInputFormat.setInputPaths( job, in );
        FileOutputFormat.setOutputPath( job, out );

        // Configure the job: name, mapper, reducer, and combiner
        job.setJobName( "HadoopProject1" );
        job.setMapperClass( MapClass.class );
        job.setReducerClass( Reduce.class );
        job.setCombinerClass( Reduce.class );

        // Configure the output
        job.setOutputFormat( TextOutputFormat.class );
        job.setOutputKeyClass( Text.class );
        job.setOutputValueClass( IntWritable.class );

        // Run the job
        JobClient.runJob(job);
        return 0;
    }

    public static void main(String[] args) throws Exception {
        // Start the WordCount MapReduce application
        int res = ToolRunner.run( new Configuration(),
                new HadoopProject1(),
                args );
        System.exit( res );
    }
}

Una vez ya tenemos hecho solamente nos queda compilar y ejecutar. Para compilar usaremos maven y nos generará un JAR en la carpeta ‘target’, la instrucción es ‘mvn compile‘.

Si nos miramos la classe del proyecto vemos que le tenemos que pasar dos parámetros, la carpeta de entrada y la de salida. Entonces para ejecutar hadoop lo haremos así:

hadoop jar <ruta hasta nuestro jar de proyecto> <classe de proyecto> <ruta de entrasa> <ruta de salida>

En mi caso quedaba algo tipo así:

hadoop jar ./target/hadoop1-1.0.jar com.lostsys.hadoop1.HadoopProject1 ./test-data ./output

Al loro! Porque también tengo que cambiarle algo de la configuración al Hadoop vía variables de entorno export HADOOP_CLIENT_OPTS="-Xmx1024m"

Hadoop puede parecer muy complicado de entender al inicio pero después es muy fácil.

Comments

One Response to “BigData con Hadoop, framework para procesar grandes cantidades de datos”
  1. […] hablamos en pasados posts de MapReduce con Hadoop. En este post explicaré como aplicar este framework de Google para hacer consultas a grandes bases […]

Leave a Reply

© Albert Coronado Calzada