Recuerda que puedes descargarte algunos de los ejemplos en la pestaña de Código Fuente

jueves, 31 de enero de 2013

El Clúster Hadoop y sus 5 demonios


Una vez que hemos visto teóricamente qué es Hadoop y sus dos partes principales HDFS y MapReduce, vamos a ver quién hace que todo esto funcione.

Un Clúster Hadoop es un conjunto de máquinas donde se ejecuta HDFS. Cada máquina es un nodo del clúster. La ventaja de este tipo de sistemas distribuídos es que las máquinas pueden ser de bajo coste y que la infraestructura puede escalar de forma horizontal facilmente.

Un Clúster puede tener como poco un sólo nodo y como máximo varios miles (hasta 30 000 a día de hoy según la web de Apache). Cuantos más nodos, mejor rendimiento.

Para que Hadoop funcione hay 5 demonios que lo manejan repartidos en dos tipos de máquinas.
Los 5 demonios son:
  • NameNode
  • Secondary Namenode
  • DataNode
  • JobTracker
  • TaskTracker

Cada demonio se ejecuta en su propia máquina virtual de Java (JVM)

Y los dos tipos de máquinas son:
  • Master Node: Que incluye el NameNode, el Secondary NameNode y el JobTracker
  • Slave Node: Que incluye los DataNode y el TaskTracker.

Algo muy importante que hay que tener claro es que no es lo mismo HDFS que MapReduce, en una aplicación Hadoop participan las dos partes, y quizás varios de los demonios se están ejecutando en las mismas máquinas, pero hay que tener claro que no son lo mismo, cuál pertenece a qué parte y cómo funcionan.

Demonios Hadoop

Antes de empezar a describir los distintos demonios estaría bien aclarar la terminología:

  • Job: Es una ejecución completa de una aplicación. La ejecución de todos los Mappers y Reducers de todos los datos.
  • Task: Es la ejecución de un sólo Mapper o de un sólo Reducer sobre un conjunto de datos.


NameNode

Es el nodo máster encargado de gestionar el namespace del sistema de ficheros.
También se encarga del mantenimiento de los metadata de todos los ficheros y directorios que forman parte del sistema HDFS.

Conoce los DataNodes del clúster y sabe cómo están repartidos en estos DataNodes los diferentes bloques que pertenecen a un fichero.

Todos los metadata los tiene en RAM para acceder más rápido, aunque también existe una copia de esta información en el disco duro (de esta forma, no se pierden estos metadata si se apaga el NameNode),

Tiene dos funciones:

Por un lado, cuando llega un nuevo fichero, es quien se encarga de decir qué bloques van y dónde en el clúster. No hay movimiento de datos a través del NameNode, sino que ese fichero se particiona y los bloques van directamente a guardarse en los DataNodes. Luego el NameNode actualiza su metadata.

Por otro lado, cuando una aplicación cliente quiere leer un fichero ésta se comunica con el NameNode para determinar qué bloques forman el fichero y dónde están y posteriormente ir a buscarlos a los DataNodes correspondientes.

Si el NameNode deja de funcionar, el sistema no puede seguir usándose. Y si además el NameNode se destruye, todos los datos del clúster se perderían ya que no habría forma de reconstruir los ficheros en base a los bloques que se encuentran en los DataNodes (a no ser que tengamos una copia de seguridad de los metadata de HDFS en otro servidor).

Secondary Namenode

Este demonio causa un poco de confusión, ya que a primera vista parece una copia de seguridad o backup del NameNode, pero hay que tener mucho cuidado, ya que NO lo es.

Su papel consiste en realizar una tarea de mantenimento de los ficheros de metadata del NameNode (consolidando el fichero "fsimage" con el fichero de logs "edits").

También hay que decir que hay un cambio entre la versión CDH3 y la versión CDH4 de Hadoop.
En la versión CDH3, sigue siendo el Secondary NameNode que se encarga tan sólo de tareas de mantenimiento del NameNode.
En la versión CDH4, se introduce un nuevo concepto: la Alta Disponibilidad. Si esta está activa, el Secondary NameNode desaparece y pasa a ser el Standby NameNode.

DataNode

Los DataNode son los nodos encargados de almacenar los bloques de datos en el clúster Hadoop.
Almacenan los bloques e informan periódicamente al NameNode las listas de bloques que están almacenando.

Cuando un cliente quiere leer un fichero, primero se comunica con el metadata del NameNode quien le dice dónde están y cómo se distribuye el fichero a leer.
Luego el cliente pasaría a conectarse directamente con los DataNode correspondientes sin que los datos pasen por el NameNode.

JobTracker

Se encarga de gestionar todo el Job (uno o varios) que ha solicitado un cliente.
Es decir, cuando recibe la petición, asigna tareas (task) Map y Reduce a los nodos del clúster.

También se encarga de saber cuáles son TaskTracker existentes. En caso de fallo de un TaskTracker, recupera las tareas map o reduce que ejecutaba ese TaskTracker y las asigna a otro.

Finalmente, gestiona el scheduling entre los distintos jobs MapReduce.

TaskTracker

Cada nodo ejecuta un demonio del TaskTracker, y es el responsable de crear instancias del Map o del Reduce  y de reportar la situación del proceso al JobTracker.

Para disfrutar de la localización de los datos, es imprescidible que el TaskTracker esté instalado en cada nodo que contenga un DataNode.


Por último vamos a ver que existen tres modos de ejecutar un cluster Hadoop:

  • Local: No se usa HDFS, sino el sistema de ficheros nativo del ordenador. Todo Hadoop se ejecuta en un único ordenador. Tampoco existe ningún demonio MapReduce. Cuando un cliente ejecuta un Job MapReduce en este modo el programa cliente "contiene" el demonio JobTracker y TasckTracker.
  • Pseudo-Distribuído: En una máquina tienes los cinco demonios funcionando.
  • Distribuído: Dispones de un clúster de dos o más nodos con los demonios separados en Master Nodes y Slave Nodes y funcionando en paralelo.

sábado, 26 de enero de 2013

Hadoop Distributed File System (HDFS)


El HDFS es el sistema de archivos distribuído de Hadoop.

Los datos se dividen en bloques de 64MB o 128MB, estos bloques se replican en un número configurable de veces (por defecto 3) y se distribuyen en distintos nodos del clúster. Esto es porque HDFS supone que algún componente del sistema puede fallar, así que siempre va a tener disponible alguna de las copias. Por otro lado, tienen que existir tantos bloques como hayamos configurado, por eso, si HDFS detecta que un componente no funciona, se encargará de saber qué bloques estaban en ese componente y replicarlos por el resto del clúster.

Es importante saber que cuando un fichero se divide en bloques, si un bloque queda "incompleto" (respecto del tamaño del bloque establecido), ese espacio nunca se va a rellenar ni utilizar con datos de otro fichero.

Este sistema de archivos está más pensado para tener un número de ficheros razonable (no más de algunos millones) de un tamaño bastante grande (del orden del tamaño de bloque HDFS o más grande aún). Es decir, con HDFS es mejor tener menos ficheros, pero más grandes (un ítem de metadatos ocupa entre 150 y 200 bytes de memoria RAM en el NameNode).
También es más óptimo para lecturas en streaming.

Está escrito en Java. Y los bloques de datos HDFS se escriben en ficheros (dentro del sistema de archivos estándar del servidor, por ejemplo ext4) en unos directorios específicos de los nodos esclavos (se encargaría el administrador) sólo una vez y no se les puede añadir más información.

Para que HDFS pueda ser un sistema de archivos distribuído, se ha de separar los datos de los metadatos. Para esto utiliza dos tipos de nodos: el NameNode y los DataNodes de los que ya hablaré más detalle en otra entrada.
Resumidamente el NameNode contiene los metadatos, es quien se encarga de dividir y distribuir los bloques por los DataNodes del clúster. Cuando un cliente quiere hacer una lectura de los datos, primero va a preguntar al NameNode, que es quien sabe dónde está cada bloque, y luego va a leer los datos bloque a bloque y en cada uno de los nodos que los contienen.

Características:
  • Almacenamiento redundante
  • Tolerancia a fallos
  • Mecanismo de checksums
  • Política de una escritura (write-once), preparado para muchas lecturas.
  • Escalabilidad horizontal
  • No implementa POSIX
Bloques HDFS

Un cliente puede acceder a HDFS a través de un terminal utilizando los comandos propios de HDFS o vía la API de Java a través de una aplicación.
Y aunque yo o mucha gente que lea el blog sean perfiles de desarrollo, es muy importante saber moverse y tener unos conocimientos básicos de cómo funciona este sistema de ficheros a través del terminal.
Para acceder a través de la línea de comandos se hace con el comando:

     $ hadoop fs

Por sí solo este comando no hace nada (sólo muestra la ayuda), luego existen múltiples comandos que ayudarán al usuario a hacer ciertas interacciones.

Cuando accedemos a través del terminal hay que tener muy claro cuál es nuestro sistema de ficheros tradicional y cuándo estamos en HDFS.

Algunos de estos comandos asociados a hadoop son:
  • Comando encargado de copiar el archivo ficheroLocal.txt que se encuentra en el directorio actual de mi sistema de ficheros local a HDFS, el archivo se llamará ficheroHDFS.txt, pero se encontrará en el directorio HDFS configurado por nuestro administrador (nuestra carpeta de usuario en HDFS):
          $ hadoop fs -put ficheroLocal.txt ficheroHDFS.txt
  • Ahora el comando encargado de copiar un fichero desde HDFS a nuestro sistema de ficheros local:
                    $ hadoop fs -get ficheroHDFS.txt ficheroLocal.txt
  • Si queremos listar el contenido de nuestro directorio HDFS (nuestra carpeta de usuario):
          $ hadoop fs -ls
  • Para mostrar el contenido de un fichero en nuestra carpeta de usuario HDFS:
                    $ hadoop fs -cat ficheroHDFS.txt
  • Queremos crear un directorio en HDFS (en nuestra carpeta de usuario)
                    $ hadoop fs -mkdir miDirectorio
  • Queremos borrar un directorio y todo su contenido:
                    $ hadoop fs -rm -r miDirectorio


Sobre cómo acceder con la API de Java, sería a través del FileSystem API, pero es una parte extensa y ya lo mostraré en otra entrada más adelante.

martes, 22 de enero de 2013

Desventajas de Hadoop


Como hemos visto en entradas anteriores, Hadoop es una tecnología que mejora considerablemente respecto de los típicos sistemas distribuídos.
Eso no quita que tenga una serie de desventajas y que si en algún momento estamos estudiando si usarlo o no, hay que tenerlas en cuenta.

En lo que respecta al HDFS:
  • Latencia para el acceso a datos: HDFS está orientado a procesos batch y operaciones en streaming. Por lo tanto, la latencia de cualquier operación IO no ha sido optimizada y sistemas de archivos tradicionales (como ext4, XFS...) suelen ser más rápidos en estos aspectos.
  • Cantidades grandes de ficheros pequeños: El límite del número de ficheros en este sistema está limitado por la memoria del NameNode, que es en su RAM donde se encuentran los metadata. Cada fichero, directorio y bloque ocupa un tamaño de entre 150 y 200 bytes en los metadata, lo que quiere decir, que si hay millones de ficheros pequeños va a ocupar mucho más espacio en la RAM que si tenemos menos cantidad de ficheros de gran tamaño (recomendable 100 MB o más).
  • Escribe una vez, lee varias: En HDFS los ficheros solo se pueden escribir una vez (aunque HDFS se ha mejorado con el modo "append", Cloudera no suele recomendarlo porque no lo considera estable).
  • No se puede acceder con los comandos tradicionales de Linux (ls, cat, vim...). Esto complica mucho la integración con otras herramientas comerciales (como sistemas de backup, por ejemplo). Y aunque exista "HDFS fuse" para montar HDFS como cualquier otro sistema de archivo Linux, esta solución no ofrece un buen rendimiento.

En lo que respecta a MapReduce:
  • Es muy difícil de depurar: Al procesarse el programa en los nodos donde se encuentran los bloques de datos, no es fácil encontrar los fallos de código. Tampoco es conveniente utilizar funciones de escritura de logs en el código ya que eso podría suponer un gran aumento en la ejecución de procesos MapReduce.
  • No todos los algoritmos se pueden escribir con el paradigma MapReduce. Por ejemplo, el famoso algoritmo de grafos Dijkstra, al necesitar un procesamiento secuencial, no se puede escribir en MapReduce.
  • Latencia: cualquier job MapReduce suele tardar por lo menos 10 segundos. Por lo tanto, si el volumen de información a tratar es pequeño, es posible que Hadoop no sea la solución más rápida.