MapReduce y Hadoop: Big Data para gente de Marketing (5)

MapReduce es el modelo de programación utilizado en Hadoop que, básicamente, le hace la vida más fácil a los programadores a la hora de trabajar con grandes volúmenes de datos distribuidos a través de múltiples máquinas que va a trabajar en paralelo dentro de un mismo cluster .

Si queremos aprovechar las capacidades de combinar los esfuerzos de varias máquinas en paralelo para realizar nuestra trabajo (job) lo primero que vamos a necesitar es expresar ese trabajo en MapReduce. Hay que entender que MapReduce no es un lenguaje de programación sino un modelo sobre el que se puede programar usando distintos lenguajes de programación, los más comunes son Java y Python.

Hadoop MapReduce

El trabajo de MapReduce se realiza en dos fases diferentes: Map y Reduce (¡sorpresa!). Para ello el programador tendrá que crear dos funciones ad hoc para el trabajo que quiera realizar denominadas mapper y reducer respectivamente. En estas dos funciones es donde el programador va a expresar la lógica de negocio, lo que quiere conseguir con los datos.

Precisamente esta es la forma en que MapReduce le facilita la vida al programador, ya que éste sólo se tiene que preocuparse de la lógica de negocio mientras que MapReduce se encarga de automatizar distribuir el procesado de los datos en paralelo a través de diferentes nodos  incluida la monitorización de todo el proceso para que, si falla alguno de los nodos, tenga capacidad de reconducir el proceso sin que el programador se tenga que preocupar de nada.

Hadoop puede trabajar con todo tipo de datos pero para procesarlos acabará transformándolos. La necesidad de esta trasformación es bastante lógica, MapReduce necesita un formato lo suficientemente flexible que le permita trabajar con cualquier tipo de datos. Para ello MapReduce necesita acordar una estructura común con la que poder operar con todos ellos y elige usar una estructura de datos en formato de pares clave (key), valor (value).

Cualquier dato puede expresarse en formato clave/valor, alguno ejemplos ilustrativos podrían ser:

  • En la base de datos de clientes un ID de un cliente (clave) puede estar asociado con el número de compras realizadas (valor)
  • Al indexar el contenido de un libro podemos relacionar una determinada palabra (clave) con el número de páginas en las que aparece (valor)

Veamos un ejemplo del proceso completo de MapReduce incluyendo la transformación de datos en pares clave/valor para que se entienda mejor. De todos los ejemplos que he encontrado para explicar como funciona MapReduce de manera intuitiva creo que este sencillo diagrama, de la introducción a Hadoop del blog de Trifork, ayuda a entender los conceptos clave:
Fases en MapReduce

  1. Digamos que nuestro objetivo es examinar el contenido de las tres frases en el imput, la entrada de datos. Para empezar el trabajo se subdivide en tres tareas diferentes, una para cada una de las frases, y se distribuye en tres nodos distintos para su procesado en paralelo.
  2. El proceso del mapping realiza la primera parte del trabajo y para ello trasforma en pares clave/valor los datos, en este ejemplo la clave es la palabra y el valor es el resultado de una función que cuenta uno cada vez que aparece en la frase (word count). En el caso de la frase Car Car River esto se traduce en la creación de una lista de pares donde Car,1 aparece dos veces, una por cada vez que aparece en la frase.
  3. A continuación se produce el proceso del servicio Shuffle and Sort, una tarea que tiene lugar en el buffer de memoria de la propia máquina (nodo). Lo que ocurre a continuación es el resultado de organizar los diferentes casos y ordenarlos para preparar la tarea para el Reducer
  4. En la fase de Reduce, en este ejemplo, se suma cada caso para cada clave ya que las claves en el output tienen que ser únicas. Ahora se creará el output una vez más siguiendo el formato clave (la palabra) y valor (la suma de casos detectados en las diferentes claves). Esta fase, por defecto, ocurrirá en un mismo nodo.
  5. Finalmente el Output de datos es la lista de pares/valor de todos los casos reagrupados para ofrecer una respuesta única al cliente que realizo la petición.

Me gusta particularmente este ejemplo no sólo por lo sencillo que hace algo que puede llegar a ser mucho más complejo, que ya me parece que tiene un gran valor. También me gusta porque esta muy cerca del fin original en la concepción de MapReduce por parte de Google, indexar el contenido de la WWW. El proceso de indexación se ha vuelto mucho más sofisticado con el paso del tiempo pero, en aquellos tiempos, una de las partes clave del proceso era precisamente la extracción del contenido (texto) de cada página de un sitio web sobre la que poder descomponer las keywords que allí aparecían y contar cuantas veces se repetía en el texto (frecuencia).

En este origen se encuentra precisamente uno de los problemas que tuvo la versión 1 de MapReduce y que llevó al desarrollo de YARN, como veremos en el próximo post de la serie.

En la versión original de MapReduce (MapReduce 1) entran en juego dos componentes para realizar la tarea del ejemplo: JobTracker y TaskTracker.

JobTracker

El es responsable de recoger la petición del cliente desde el front-end y de asignar a los TaskTrackers las tareas concretas que deberán realizar en el proceso. El JobTracker está en el nodo maestro (NameNode), recordemos que es donde se guarda la información de en qué nodo (DataNode) está cada fragmento de cada fichero. Los nodos en los que se van a ejecutar las tareas definidas por el JobTracker serán precisamente los DataNodes, en donde viven los datos. En el caso de que, por cualquier motivo, uno de los nodos fallase el JobTracker se encargaría de redirigir la tarea a otro nodo donde estuviera alojada una réplica de los datos.

TaskTracker

Se trata de un demonio (daemon) que acepta y ejecuta las tareas asignadas: map, reduce y shuffle. Adicionalmente el TaskTracker envía una señal al JobTracker para advertirle de que está vivo y listo para ejecutar la tarea. Una vez iniciada mantiene un feedback continuo de su progreso.

Proceso de un trabajo en MapReduce

Veamos ahora un ejemplos de un proceso completo desde la perspectiva del uso de los diferentes nodos y la gestión de tareas realizadas entre el JobTracker y las diferentes tareas del TaskTracker en cada uno de los DataNodes:

 

Diagrama de trabajo en MapReduce
Visto en el blog de Rohit Menon
  1. Un cliente mediante un programa en MapReduce envía un trabajo a realizar al JobTracker, en el ejemplo anterior un conteo de las palabras en una serie de frases.
  2. El JobTracker obtiene del NameNode la ubicación de los datos en los DataNodes, a partir de ahí el JobTracker intenta introducir el programa del cliente en HDFS y asigna las tareas que tienen que realizar los TaskTrackers en los nodos en los que ha localizado los datos.
  3. El TaskTracker inicia las tareas Map en cada DataNode trasladando el programa del cliente de la ubicación compartida HDFS al nodo donde se van a ejecutar las tareas (los tres nodos que trabajan con cada una de las frases en el diagrama).
  4. Cuando se finaliza la tarea de Mapear (Map) se genera un fichero intermedio a nivel local en el nodo del TaskTracker. Este fichero es el que se pasa a la tarea de Reduce.
  5. El proceso de Reduce trabaja con todos los datos recibidos de las tareas de Mapeo (Map) y, una vez procesado, escribe el output final en el sistema de ficheros HDFS. Al finalizar borra los datos intermedios generados por el TaskTracker en los distintos nodos.

Una de las diferencias claves con otros sistemas de gestión de datos es que, como acabamos de ver, en Hadoop llevamos el programa hasta el nodo en el que se alojan los datos y no al revés. Este cambio de filosofía es precisamente el que permite la eficiencia del procesado distribuido de los datos en Hadoop.

En la versión 2 de MapReduce se introduce un nuevo gestor de recursos llamado YARN (Yet Another Resource Negociator). La llegada de YARN sobre MapReduce cambia el funcionamiento de algunas de las cosas que hemos visto en este post. En el próximo post de esta serie me centraré en explicar cual es la función de YARN y como afecta al funcionamiento de la nueva versión de MapReduce.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *