Creación de un entorno de desarrollo Hadoop con Hortonworks

Creación de un entorno de desarrollo Hadoop con Hortonworks

Hortonworks

Introducción


Para trabajar con grandes volúmenes de datos las soluciones tradicionales como bases de datos transaccionales dejan de ser factibles. En estos casos hay que recurrir a un nuevo enfoque basado en computación distribuida, dentro de la cual la solución más ampliamente utilizada es Hadoop. Este es un framework que cuenta con todos los componentes necesarios para trabajar en un único ambiente de trabajo. Antes de continuar con este post, si no están familiarizados con Hadoop les recomiendo leer mi anterior post Qué es Hadoop? | Introducción e Instalación. Ahora bien, ¿como podemos hacer desarrollos o si quiera aprender a utilizar esta tecnología si no poseemos un cluster configurado? Hemos visto en el post anterior, que realizar una instalación de Hadoop desde cero no es algo simple, y en general no es algo que vayamos a necesitar realizar por nosotros mismos. Entonces, ¿hay forma de prepara un entorno de trabajo de manera simple? La respuesta es que sí, y en este post veremos como.

Hortonworks


Para prepara un entorno de trabajo realmente no hay que hacer más que descargar una maquina virtual (MV) que ya posea Hadoop instalado y luego realizar unas pocas configuraciones. A este tipo de MV (que ya poseen software instalado y listo para usar) se las denomina Sandbox. ¿Pero de donde sacamos un Sandbox de Hadoop? La respuesta es que en estos momento existen dos grandes proveedores. Uno es Hortonworks y el otra es Cloudera. Yo en este post voy a mostrar como trabajar con Hortonworks, dado que es el que siempre utilicé y conozco mejor, aunque hay que aclara que realmente no hay grandes diferencias entre ambas. Entonces, comenzamos por descargar el Sandbox entrando al sitio web de Hortonworks y yendo a Products → Download → Sandbox. Luego a la sección Hortonworks Data Platform y seleccionamos la descarga para el virtualizador que utilicemos (VirtualBox o VMware). En mi caso selecciono VMware. Luego nos pide algunos datos y nuestro correo para comenzar a enviarnos spam, y finalmente comienza la descarga. La descarga ocupa cerca de 10Gb por lo que hay que tener algo de paciencia hasta que termine. Cuando finaliza la descarga obtenemos un archivo con formato .ova que es un generador de MV para VMware. Luego le damos doble click a este, y finalmente a import y esperamos a que termine de crearse la MV. Finalizada la creación de la MV procedemos a encenderla y esperar que esté lista para ser utilizada. Cuando esto ocurra vemos que aparece la siguiente pantalla, en la que se nos indica la IP y el puerto para conectarnos mediante un explorador web.     Y ya tenemos listo el entorno de trabajo. Así de simple. Ahora veamos como acceder a las herramientas que provee el Sandbox. Para esto vamos a ADVANCE HDP, en donde vemos una serie de componentes, entre los cuales los más importantes son AMBARI y el cliente SSH. Cada uno de estos tiene asociado puerto mediante el cual lo accedemos. Por ejemplo, el puerto para acceder a Ambari es el 8080.

Ambari


Ambari es una plataforma para administración, aprovisionamiento y monitoreo de Hadoop. A través de esta podemos realizar configuraciones de Hadoop y todos sus componentes. También posee un administrador de archivos, un cliente para trabajar con HIVE y con PIG, y varias herramientas más. No obstante, todas las herramientas que brinda poseen un overhead importante que ralentiza las tareas, por lo cual yo prefiero trabajar siempre que sea posible desde la linea de comando mediante SSH,

Linea de comandos


Para poder acceder a una linea de comandos del Sandbox lo hacemos como con cualquier otra computadora. Si utilizamos Linux (o Putty en Windows) basta con indicar que queremos utilizar SSH sobre la IP indicada y el puerto 22. Pero en el caso de Windows tenemos integrado un cliente de linea de comando en el explorador web que en mi caso particular encuentro muy cómodo. Para acceder a él ponemos en el explorador la IP y el puerto 4200. Independientemente de como entremos, la primer vez que nos logueamos debemos usar “username/password: root / hadoop”. Una vez dentro, se nos pide cambiar la clave, y hecho esto podemos comenzar a trabajar con toda libertad. Podemos trabajar con el HDFS, con Hive, con Spark, etc. Por ejemplo, si queremos trabajar con Hive basta con ingresar a este desde la linea de comando. Por defecto la instalación trae un par de “bases de datos” que podemos usar para pruebas.

HDInsignt (Azure)


¿Para que nos serviría poder tener este entorno de trabajo? La razón principal es para hacer desarrollo en una computadora local y después realizar el paso a producción sin insumir costos de desarrollo elevados. Por ejemplo, si tomamos el caso de la plataforma de Microsoft (Azure), posee un servicio llamados HDInsight que básicamente es un cluster Hadoop desarrollado por Hortonworks. Este es similar al Sandbox del cual estuvimos hablando, salvo por el hecho clave de que al momento de crearlo podemos indicar el tamaño del cluster. Como normalmente en trabajos con grandes volúmenes de datos se requiere de varias computadoras de potencia y memoria moderada a grande, y dado que en la nube se paga por tiempo que se utilizan los recursos, resulta inviable hacer un desarrollo directo en la nube. En cambio, el procedimiento habitual es hacer los desarrollos en una computadora local (trabajando con una muestra de los datos si es necesario) y luego que se tiene el sistema funcionando en local se implementa en la nube configurando el cluster para que se cree, haga lo que tenga que hacer y se destruya automáticamente, evitando que esté encendido y sin uso (lo cual es igual a tirar dinero).  

Comentarios

Qué es Hive (Hadoop) | Introducción e Instalación

Qué es Hive (Hadoop) | Introducción e Instalación

Introducción a Hive

 

qué es Hive


Apache Hive es un software que forma parte del ecosistema de Hadoop. Es utilizado para gestionar enormes datasets almacenados bajo el HDFS de Hadoop y realizar consultas (queries) sobre los mismos.

Para esto, Hive implementa una variante al SQL, llamada HQL (Hive QL). Esta variante no soporta la especificación SQL-92 completa, pero sí una gran parte. Realmente, cuando se ejecutan consultas HQL, Hive convierte la consulta HQL a un trabajo MapReduce que es ejecutado para obtener los datos. La finalidad de esto es permitir a usuarios que no cuenten con experiencia en programación de algoritmos MapReduce (que suelen ser bastante laboriosos), pero que sí cuenten con conocimientos de SQL, poder consultar datos.

Un punto a favor de Hive es que trabajar con este es similar a trabajar con bases de datos tradicionales. Desde Hive debemos estructurar los datos agrupándolos en tablas, con sus columnas y tipos de datos asociados. Pintar en estas tablas los datos, luego procesarlos y finalmente analizarlos. No obstante, no hay que olvidar que Hive no es un motor de bases de datos.

El inconveniente que presenta Hive es que, al necesitar procesar la consulta y traducirla a lenguaje Java para crear el MapReduce, la latencia de respuesta es alta. A su vez, como mencionamos, tampoco soporta todo el lenguaje SQL, transacciones ni índices.

Para poder empezar a trabajar con Hive debemos, primero que nada, instalarlo. En este post veremos como hacer esto, y en futuros post comenzaremos aprender sobre otros temas como lenguaje HQL, tipos de datos, funciones predefinidas (built-in) y definidas por el usuario (UDF), etc.

 

Instalación


Instalación Hadoop

Lo primero es tener instalado y corriendo Hadoop en nuestro equipo. Caso contrario, pueden seguir este otro tutorial donde explicar como hacer esto:

 

Instalación Hive

Hecho esto, debemos bajar el instalador de Hive desde su web. Una vez descargado, lo descomprimimos y movemos a la carpeta ‘/usr/local/hive/’:

sudo mv apache-hive-2.1.0-bin /usr/local/hive

Nos aseguramos que el owner de la carpeta y sus contenidos sea el usuario Hadoop:

hadoop@ubuntu:/usr/local$ ls -l /usr/local/hive/
total 140
drwxrwxr-x 3 hadoop mauricio  4096 Nov  5 00:34 bin
drwxrwxr-x 2 hadoop mauricio  4096 Nov  5 12:20 conf
-rw-r--r-- 1 hadoop root         0 Nov  4 23:52 derby.log
drwxrwxr-x 4 hadoop mauricio  4096 Oct 11 02:59 examples
drwxrwxr-x 7 hadoop mauricio  4096 Oct 11 02:59 hcatalog
drwxr-xr-x 3 hadoop root      4096 Nov  5 12:22 iotmp
drwxrwxr-x 2 hadoop mauricio  4096 Oct 11 02:59 jdbc
drwxrwxr-x 4 hadoop mauricio 12288 Nov  5 11:48 lib
-rw-r--r-- 1 hadoop mauricio 29003 Jun  3 07:43 LICENSE
-rw-r--r-- 1 hadoop mauricio   513 Jun  3 07:43 NOTICE
-rw-r--r-- 1 hadoop mauricio  4122 Jun  3 07:43 README.txt
-rw-r--r-- 1 hadoop mauricio 50294 Jun 16 20:43 RELEASE_NOTES.txt
drwxrwxr-x 4 hadoop mauricio  4096 Oct 11 02:59 scripts
drwxr-xr-x 3 hadoop root      4096 Nov  4 23:52 ${system:java.io.tmpdir}

o en caso contrario, cambiamos esto con:

sudo chown -R hadoop /usr/local/hive/

Finalmente, agregamos al archivo ~/.bashrc del usuarios Hadoop las siguientes variables de entorno:

# HIVE
export HIVE_HOME=/usr/local/hive
export PATH=$PATH:$HIVE_HOME/bin
export CLASSPATH=$CLASSPATH:/usr/local/Hadoop/lib/*:.
export CLASSPATH=$CLASSPATH:/usr/local/hive/lib/*:.

Recordar que cada vez que modificamos el archivos .bashrc debemos actualizar las variables de entorno del sistema con source ~/.bashrc.

Configuración

Ahora debemos configurar una base de datos que utilizará Hive para guardar sus metadatos. Por defecto se utilizar una llamada Derby, pero que solo es apto para entornos de testing. Nosotros instalaremos y configuraremos esta base en MySQL. Entonces, lo primero es instalar MySQL:

sudo apt-get install mysql-server libmysql-java

y creamos el siguiente enlace simbólico:

ln -s /usr/share/java/mysql-connector-java.jar $HIVE_HOME/lib/mysql-connector-java.jar

Ahora nos logueamos en MySQL y creamos una base de datos donde se almacenaran los metadatos que genere Hive. Luego de crear la base de datos, debemos rellenarla con el esquema que se correspondiente que se encuentra en ‘$HIVE_HOME/scripts/metastore/upgrade/mysql/’:

$ mysql -u root -p

mysql> CREATE DATABASE metastore;
mysql> USE metastore;
mysql> SOURCE /usr/local/hive/scripts/metastore/upgrade/mysql/hive-schema-0.14.0.mysql.sql;

y le creamos un usuarios a Hive para que pueda acceder a la base de datos:

mysql> CREATE USER 'hiveuser'@'%' IDENTIFIED BY 'hivepass'; 
mysql> GRANT all on *.* to 'hiveuser'@localhost identified by 'hivepass';
mysql> flush privileges;

Ahora debemos incluir en el archivo /usr/local/hive/conf/hive-site.xml las siguientes lineas que indican a Hive como conectarse con la base de datos:

 <property>
   <name>javax.jdo.option.ConnectionURL</name>
   <value>jdbc:mysql://localhost/metastore?createDatabaseIfNotExist=true</value>
   <description>metadata is stored in a MySQL server</description>
 </property>
 <property>
   <name>javax.jdo.option.ConnectionDriverName</name>
   <value>com.mysql.jdbc.Driver</value>
   <description>MySQL JDBC driver class</description>
 </property>
 <property>
   <name>javax.jdo.option.ConnectionUserName</name>
   <value>hiveuser</value>
   <description>user name for connecting to mysql server</description>
 </property>
 <property>
   <name>javax.jdo.option.ConnectionPassword</name>
   <value>hivepass</value>
   <description>password for connecting to mysql server</description>
 </property>

Y ya estamos listos. Con esto deberíamos poder iniciar iniciar Hive… bueno, casi. Cuando he intentado ingresar a Hive me ha salido un error de permisos de escritura que he solucionado (googleando) añadiendo las siguientes lineas al archivos mismo archivo:

<property>
  <name>hive.querylog.location</name>
  <value> /usr/local/hive/iotmp</value>
  <description>Location of Hive run time structured log file</description>
</property>
<property>
  <name>hive.exec.local.scratchdir</name>
  <value>/usr/local/hive/iotmp</value>
  <description>Local scratch space for Hive jobs</description>
</property>
<property>
  <name>hive.downloaded.resources.dir</name>
  <value>/usr/local/hive/iotmp</value>
  <description>Temporary local directory for added resources in the remote file system.</description>
</property>

 

Testing

Vamos a comprobar ahora que la instalación se haya realizado correctamente.

Primero revisamos si Hive responder. Para esto ingresamos hive –version:

$ hive --version
Hive 2.1.0
Subversion git://jcamachguezrMBP/Users/jcamachorodriguez/src/workspaces/hive/HIVE-release2/hive -r 9265bc24d75ac945bde9ce1a0999fddd8f2aae29
Compiled by jcamachorodriguez on Fri Jun 17 01:03:25 BST 2016
From source with checksum 1f896b8fae57fbd29b047d6d67b75f3c

y ahora creamos una base de datos (realmente no es una base de datos lo que estamos creando, pero la podemos tratar como tal):

$ hive

...

hive> create table mauricio_test(id int, name string);
OK
Time taken: 2.424 seconds

Vamos a ver que tenemos en la base de datos de MySQL que creamos previamente:

$ mysql -u root -p

mysql> use metastore;
mysql> select * from TBLS;
+--------+-------------+-------+------------------+--------+-----------+-------+---------------+---------------+--------------------+--------------------+----------------+
| TBL_ID | CREATE_TIME | DB_ID | LAST_ACCESS_TIME | OWNER  | RETENTION | SD_ID | TBL_NAME      | TBL_TYPE      | VIEW_EXPANDED_TEXT | VIEW_ORIGINAL_TEXT | LINK_TARGET_ID |
+--------+-------------+-------+------------------+--------+-----------+-------+---------------+---------------+--------------------+--------------------+----------------+
|      1 |  1478359381 |     1 |                0 | hadoop |         0 |     1 | hive          | MANAGED_TABLE | NULL               | NULL               |           NULL |
|      6 |  1478371335 |     1 |                0 | hadoop |         0 |     6 | mauricio_test | MANAGED_TABLE | NULL               | NULL               |           NULL |
+--------+-------------+-------+------------------+--------+-----------+-------+---------------+---------------+--------------------+--------------------+----------------+
2 rows in set (0.00 sec)

 

Listo! Ya tenemos preparado nuestro equipo para trabajar con Hadoop utilizando Hive.

 

Comentarios

Qué es Hadoop? | Introducción e Instalación

Qué es Hadoop? | Introducción e Instalación

qué es Hadoop

Qué es Hadoop


Apache Hadoop es un framework de código abierto utilizado para el almacenado y procesamiento de grandes volúmenes de datos en forma distribuida. Para esto utiliza lo que se conoce como commodity hardware, es decir, un conjunto de computadoras genéricas. Por sus características, Hadoop es ampliamente utilizado en Big Data, ya que permite trabajar con grandes volumenes de información a muy bajo costo.

En este post comentaremos los componentes principales del framework, e instalaremos Hadoop en una computadora virtual en modo pseudo-distribuido. Estos nos permitirá, en próximos post, comenzar a utilizarlo y aprender sin necesidad de estar en un entorno real de producción. En caso que deseen profundizar en Hadoop, les invito a que visiten la sección Getting Started del proyecto.

 

Arquitectura


La arquitectura de Hadoop sigue el paradigma de arquitectura master/slave. En el siguiente diagrama se representa esta:

 

arquitectura-hadoop

 

El master viene siendo el NameNode. Este nodo es el más importante de la arquitectura, y controla el acceso por parte de los clientes a la información, a la vez que gestiona el almacenamiento y procesamiento de los datos en los DataNodes. Esto últimos serían los slaves, también llamados workers.

Los componentes principales de la arquitectura de Hadoop son:

  • HDSF: es el sistema de archivos de Hadoop. Está diseñado para utilizar múltiples computadoras genéricas (commodity machines) agrupadas en clústers. Este es tolerante a fallas y provee una alta tasa de acceso a los datos.
  • NameNode: es el Corazón del Sistema Hadoop, y se encarga de gestionar el clúster. Almacena los metadatos de los bloques de datos, los cuales son almacenados permanentemente en el disco local en lo que es el namespace. A su vez, también conoce la ubicación de los bloques de datos en los DataNodes.
  • Secondary NameNode (opcional): tiene la responsabilidad de periódicamente copiar el namespace. En caso de que el NameNode falle, entonces el namespace almacenado en este nodo puede ser usado para reiniciar el sistema.
  • DataNode: almacenan los bloques de datos y entregan la información cuando se les solicita. Estos nodos también reportan periódicamente los metadatos asociados a los bloques de información al NameNode. En esto se ejecutan las tareas MapReduce.
  • JobTracker: es responsable de coordinar los trabajos (jobs) solicitados por los clientes. Crea las tareas MapReduce y las asigna a los diferentes TaskTrackers en los DataNodes. También comprueba si las tareas fallaron, y en tal caso las reprograma en otro DataNode. Puede ser ejecutado en el NameNode, o en un nodo separado.
  • TaskTracker: Es responsable de correr los MapReduce asignados por el JobTracker y reportar el estado de la tarea a este. Se ejecuta en los DataNodes.

 

HDFS


El sistema de archivos de Hadoop (HDFS, Hadoop Distributed File System) almacena los datos en bloques de gran tamaño. Por defecto, el tamaño de estos bloques es 64MB, con un máximo configurable de 128MB. Entonces, cuando vamos a almacenar un archivo, este el dividido en bloques de 64MB, y luego almacenado en múltiples nodos (por defecto, se almacena 1 copia de cada bloque en 3 DataNodes diferentes, cada una en un nodo diferente).

La razón principal de que se use un tamaño grande para los bloques, siendo que lo usual en otros sistemas de archivos es que esté en el orden de los KB, es para reducir el tiempo de búsqueda en estos. En general, el tiempo de búsqueda ronda los 10ms, y luego la transferencia de datos es de 100MB/s. De esta forma, el tiempo de búsqueda para bloques de 100MB es el 1% del tiempo de transferencia.

Los demás beneficios de este diseño son:

  • Como los bloques son de tamaño fijo, es fácil calcular el número de bloques que pueden ser almacenados en cada DataNodes.
  • Simplifica el almacenamiento de los datos en los DataNodes, ya que estos no necesitan conocer acerca de los mata-datos de los bloques. El NameNode es el que se ocupa de mantener esta información.
  • Los bloques son fáciles de replicar entre los DataNodes, y de esta forma proveen alta tolerancia a fallas y alta disponibilidad. Por defecto se hacen 3 copias de cada bloque de datos que son puestas en diferentes nodos. Si uno de estos falla, entonces los datos pueden ser recuperados de los otros bloques.

 

MapReduce


Hadoop se base en el paradigma MapReduce para paralelizar los procesos en dos fases. La primer fase es la de mapeo (map). En esta se realiza un escaneo de los datos de entrada y se genera una lista de pares clave-valor. Estos pares son agrupados por clave y pasados a la función reduce que se encarga de procesarlos y generar un resultado agrupado de los mismos.

En futuros post veremos más detalladamente, y con ejemplos concretos, como se realiza esto.

 

Instalación de Hadoop


Modos de funcionamiento

Hadoop tiene tres modos de funcionamiento:

  • Modo local: se ejecuta en un único nodo como un solo proceso java.
  • Modo local pseudo-distribuido: se ejecuta en un único nodo, pero cada demonio se ejecuta en un proceso java diferente.
  • Modo distribuido: se ejecuta utilizando múltiples nodos completamente distribuido.

Cuando se va a montar Hadoop en producción se lo utiliza en modo distribuido, mientras que el modo pseudo-distribuido se lo suele utilizar para desarrollo, y en nuestro caso, aprendizaje.

 

Entorno

Hadoop funciona en entornos Linux. Lo aconsejable es que para comenzar adentrarse en Hadoop se utilice una máquina virtual. De este modo, en caso que rompamos algo bastaría con hacer un rollback a un estado previo del sistema, o simplemente reinstalar la máquina virtual sin poner el riego nuestra máquina. Yo en este caso tengo instalado en una máquina virtual en VMware un Ubuntu 16.04 (la versión LTS más actual de Ubuntu al momento de escribir este post).

A su vez, vamos a necesitar que en esta máquina tengamos instalado java. Para comprobar si es así podemos ejecutar:

$ java -version
openjdk version "1.8.0_91"
OpenJDK Runtime Environment (build 1.8.0_91-8u91-b14-3ubuntu1~16.04.1-b14)
OpenJDK 64-Bit Server VM (build 25.91-b14, mixed mode)

En caso de no tenes instalado java, bastaría con ingresar:

$ sudo apt-get install sun-java*

y luego generar la variable de entorno correspondiente:

$ export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64/

Estos comando pueden variar levemente de PC en PC, pero googleando un poco no deberían tener problemas para la instalación en caso de tener inconvenientes.

 

Instalación

Ahora comenzamos con la instalación de Hadoop. Desde este momento voy a asumir que contamos con conocimientos básicos de Linux, por lo que no me detendré a explicar los comandos que utilicemos ni demás temas vinculados al sistema operativo. En caso de que tengan dudas en algún punto, sobre Linux hay mucho escrito en la web, de modo que estoy seguro podrán encontrar sin problemas las respuestas a todas ellas.

Luego, debemos descargar Hadoop desde la sección de descarga de su web oficial. Al día de escribir este post, la versión estable más reciente es la 2.7.3, por lo que procedo a descargar los binarios. Una vez los tenemos descargados, debemos descomprimir el archivo hadoop-2.7.3.tar.gz, y mover la carpeta resultante a ‘/usr/local/’:

$ mv hadoop-2.7.3 /usr/local/hadoop

A continuación creamos un usuario para administrar y configurar Hadoop:

$ useradd -d /home/hadoop -m hadoop
$ passwd hadoop
$ usermod -a -G sudo hadoop
$ usermod -s /bin/bash hadoop

Luego, nos logueamos con el usuario creado, y agregamos las variables de entorno para este en el ‘~/.bashrc’:

$ export HADOOP_HOME=/usr/local/hadoop 
$ export PATH=$PATH:$HADOOP_HOME/bin
$ export PATH=$PATH:$HADOOP_HOME/sbin
$ export HADOOP_MAPRED_HOME=${HADOOP_HOME}
$ export HADOOP_COMMON_HOME=${HADOOP_HOME}
$ export HADOOP_HDFS_HOME=${HADOOP_HOME}
$ export YARN_HOME=${HADOOP_HOME}

Hecho esto, ejecutamos ‘source .bashrd’ para cargar la nueva configuración, y comprobamos que todo vaya bien con:

$ hadoop version
Hadoop 2.7.3
Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r baa91f7c6bc9cb92be5982de4719c1c8af91ccff
Compiled by root on 2016-08-18T01:41Z
Compiled with protoc 2.5.0
From source with checksum 2e4ce5f957ea4db193bce3734ff29ff4
This command was run using /usr/local/hadoop/share/hadoop/common/hadoop-common-2.7.3.jar

 

Configuración de SSH

Los nodos en Hadoop se comunican mediante SSH, por lo que debemos configurar este protocolo:

$ sudo apt-get install ssh
$ ssh-keygen -t rsa -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

y otorgarle permisos:

$ sudo chmod go-w $HOME $HOME/.ssh
$ sudo chmod 600 $HOME/.ssh/authorized_keys
$ sudo chown `whoami` $HOME/.ssh/authorized_keys

Una vez hecho esto, comprobamos la conexión:

$ ssh localhost

Lo siguiente a realizar es desactivar de protocolo IPv6 según indica la documentación oficial. Para esto debemos modificar las siguientes lineas del archivo ‘/etc/sysctl.conf’:

$ net.ipv6.conf.all.disable_ipv6 = 1
$ net.ipv6.conf.default.disable_ipv6 = 1
$ net.ipv6.conf.lo.disable_ipv6 = 1

Configuración del HDFS

Hasta el momento tenemos montado Hadoop para ejecutarse en modo local. Si queremos que se ejecute en modo speudo-aleatorio debemos tocar algunos archivos para configurar el HDFS.

 

core-site.xml

Nos vamos a ‘/usr/local/hadoop/etc/hadoop’ y encontramos el archivo core-site.xml. En este se pueden indicar numerosas opciones de configuración, de las cuales la que nos interesa en este momento es configurar el directorio HDFS por defecto en el localhost:

 <?xml version="1.0"?>
 <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
 
 <configuration>
   <property>
     <name>fs.default.name</name>
     <value>hdfs://localhost:8020</value>
   </property>
 </configuration>

 

hdfs-site.xml

El hdfs-site.xml contiene información sobre como Hadoop almacenará la informacion en el clúster.

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
 
<configuration>
  <property>
    <name>dfs.namenode.name.dir</name>
    <value>file:/home/hadoop/workspace/dfs/name</value>
    <description>Ruta del sistema de archivos donde el NameNode almacenará los metadatos.</description>
  </property>

  <property>
    <name>dfs.datanode.data.dir</name>
    <value>file:/home/hadoop/workspace/dfs/data</value>
    <description>Ruta del sistema de archivos donde el DataNode almacenerá los bloques.</description>
  </property>

  <property>
    <name>dfs.replication</name>
    <value>1</value>
    <description>Factor de replicación. Como tenemos una única computadora en el clúster lo ponemos a 1.</description>
  </property>
</configuration>

Y crear los directorios ‘/home/hadoop/workspace/dfs/name’ y ‘/home/hadoop/workspace/dfs/data’.

 

mapred-site.xml

Se utiliza para especificar quien realiza el MapReduce y el lugar donde se lleva a cabo. En cuanto a lo primero, lo configuramos para que sea hecho por el YARN (Yet Another Resource Negotiator), el cual es el componente del framework encargado de esta tarea. Como tenemos un único nodo en nuestro clúster, solo habrá una job map y otro reduce.

Antes de tocar el archivo, debemos renombrarlo. El nombre por defecto es mapred-site.xml.template y queremos que pase a ser mapred-site.xml. Hecho esto, pasamos a modificarlo.

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
 
<configuration>
  <property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
  </property>

  <property>
    <name>mapred.system.dir</name>
    <value>file:/home/hadoop/workspace/mapred/system</value>
    <final>true</final>
  </property>

  <property>
    <name>mapred.local.dir</name>
    <value>file:/home/hadoop/workspace/mapred/local</value>
    <final>true</final>
  </property>
</configuration>

Y crear los directorios ‘/home/hadoop/workspace/mapred/system‘ y ‘/home/hadoop/workspace/mapred/local’.

 

yarn-site.xml

Este archivo se utiliza para configurar YARN en Hadoop. Lo que vamos a hacer es habilitar la fase de Suffle para que se pueda hacer entre las fases Map y Reduce.

<configuration>
  <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
  </property>

  <property>
    <name>yarn.nodemanager.aux-services.mapreduce_shuffle.class</name>
    <value>org.apache.hadoop.mapred.ShuffleHandler</value>
  </property>
</configuration>

 

Últimos pasos


Ahora que tenemos lista la configuración debemos formatear el HDSF con:

hadoop namenode -format

y arrancar el clúster. Para esto último nos vamos a ‘/usr/local/hadoop/sbin/’ y ejecutamos:

./start-dfs.sh
./start-yarn.sh

con esto ya podemos ver, mediante el comando jps, como se han iniciado todos los procesos:

$ jps
11363 Jps
7572 SecondaryNameNode
8038 NodeManager
7239 NameNode
7384 DataNode
7737 ResourceManager

Una vez arrancado el clúster, desde un navegador web podemos verificar que se haya hecho exitosamente ingresando a ‘http://localhost:50070/’, en donde podemos ver información del NameNode y del HDFS:

 

namenode-information

 

o si quisiésemos hacer seguimiento de los jobs que se vayan ejecutando podemos ir a ‘http://localhost:8088/cluster/nodes’:

 

all-applications

Cierre


Hasta acá hemos visto de que se trata Hadoop, y hemos realizado una instalación que nos servirá para en futuros post seguir explorando el framework. Si les ha gustado, no olviden suscribirse al newsletter para estar al tanto cuando vaya subiendo nuevo contenidos. Y si tienen alguna duda, comentario o feedback, no duden en dejarlo abajo en los comentario.

 

Comentarios

Hive (Hadoop) | Funciones y Tipo de Datos

Hive (Hadoop) | Funciones y Tipo de Datos

Ahora que tenemos instalado Hive en nuestro equipo comenzaremos a aprender como utilizarlo. Dado que trabajar en Hive es similar a trabajar con bases de datos relacionales en cuento al lenguaje de consulta, en este post nos vamos a dedicar a hablar de los tipos de datos y de las funciones predefinidas (Built-in), y en una segunda parte del post hablaremos sobre las funciones definidas por los usuarios (UDF, user defined function) y haremos algunos ejemplos de como trabajar con el HQL y manipular información.

 

qué es Hive

 

Tipos de datos


Los tipos de datos en Hive son clasificados en dos tipos: primitivos y complejos.

Los tipos de datos primitivos incluyen a los enteros (integer), booleanos (boolean), cadenas (string), etc.

Tipo
TINYINT      1 byte
SMALLINT     2 byte
INT          4 byte
BIGINT       8 byte
FLOAT        4 byte
DOUBLE       8 byte
BOOLEAN      TRUE/FALSE
STRING       tamaño máximo 2GB.
TIMESTAMP    almacenar fecha y hora
DATE         almacenar solo fecha

Mientra que los tipos complejos incluyen Arrays, Maps y Structs. Estos tipos de datos son construidos utilizando datos primitivos.

  • Arrays: Contienen una lista de elementos del mismo tipo. Estos elementos son accedidos por un índice. Por ejemplo, si el campo Mascota contiene a lista de elementos [‘perro’, ’gato’, ‘loro’], el elemento ‘gato’ puede ser accedido mediante Mascota[1].
  • Maps: Contienen pares clave-valor. Cada elemento es accedido mediante su clave. Por ejemplo, un map lista_passwords conteniendo “Mauricio” como clave y “passDeMauricio” como valor, el password del usuario es accedido mediante lista_passwords[‘Mauricio’].
  • Structs: Contienen elementos de diferente tipos. Cada elementos puede ser accedido mediante la notación punto (dot notation). Por ejemplo, en una estructura auto, el color del auto puede ser recuperado mediante auto.color.

Ejemplo:

CREATE TABLE complex_data_types
(
  mascota         ARRAY<string>,
  list_passwords  MAP<string,string>,
  auto            STRUCT<color:string, rodado:float>
);

Funciones predefinidas (built-in functions)


Las funciones predefinidas en Hive se clasifican en:

  • Funciones matemáticas y numéricas: principalmente utilizadas para realizar cálculos matemáticos.
  • Funciones de fecha: principalmente utilizadas para realizar operaciones sobre campos tipo fecha (date).
  • Funciones de cadena: usadas para realizar operaciones sobre cadenas (string).
  • Funciones condicionales: usadas para comprobar condiciones, en donde se devuelva una valor Verdadera o False según se cumpla o no la condición.
  • Funciones de acumulación: usadas para encontrar el tamaño de un campo complejo como un array o un map. La única función de este tipo es SIZE, la cual encuentra el número de elementos en uno de estos tipos. La sintaxis de esta función es:
SIZE(Array<A>)
SIZE(MAP<key,value>)
  • Funciones de conversión: usada para convertir un dato de un tipo a otro. La única función de esto tipo es CAST. La sintaxis de esta función es:
CAST(expr as <type>)
  • Funciones generadoras: estas funciones transforman un campo tipo array en múltiples campos. La única función de este tipo es EXPLODE, la cual toma un campo tipo array como entrada, y como salida devuelve los elementos del array en filas separados. Cuando se usa esta función en el SELECT, no se puede especificar ninguna otra columna. La sintaxis de esta función es:
EXPLODE(ARRAY<A>)

 

Funciones matemáticas y numéricas


 

ABS( double n ): valor absoluto de un número.

ABS(-1)

 

ACOS( double n ): arco-coseno de n. En caso de que n no esté en el intervalo [-1; +1] devuelve NULL.

ACOS(0.8)

 

ASIN( double n ): arco-seno de n. En caso de que n no esté en el intervalo [-1; +1] devuelve NULL.

ASIN(0.2)

 

BIN( bigint n ): convierte n a formato binario.

BIN(25)

 

CEIL( double n ), CEILING( double n ): redondea el valora decimal n al entero más cercano más pequeño.

CEIL(5.25)

 

CONV( bigint n, int from_base, int to_base ): convierte un número de una base a otra.

CONV(100, 10,2)

 

COS( double n ): devuelve el coseno de n, el cual debe estar indicado en radianes.

COS(3.14)

 

EXP( double n ): devuelve e^n.

EXP(5)

 

FLOOR( double n ): devuelve el entero superior más cercano a n.

FLOOR(10.9)

 

HEX( bigint n ): convierte el valor n a hexadecimal.

HEX(17)

 

HEX( string n ): convierte cada caracter en su representación hexadecimal.

HEX(‘ABC’)

 

LN( double n ): devuelve al logaritmo natural de n

LN(1.45)

 

LOG( double b, double n ): devuelve el logaritmo en base b de n.

LOG(3, 66)

 

LOG2( double n ): devuelve el logaritmo en base 2 de n.

LOG2(44)

 

LOG10( double n ): devuelve el logaritmo en base 10 de n.

LOG10(1000)

 

NEGATIVE( int n ),  NEGATIVE( double n ): devuelve el valor negativo de n.

NEGATIVE(10)

 

PMOD( int m, int n ), PMOD( double m, double n ): devuelve el módulo de la división entre m y n.

PMOD(3,2)

 

POSITIVE( int n ), POSITIVE( double n ): devuelve el valor positivo de n.

POSITIVE(-10)

 

POW( double m, double n ), POWER( double m, double n ): devuelve m^n.

POW(10,2)

 

RAND( [int seed] ): devuelve un número aleatorio.

RAND()

 

ROUND( double m[, int n] ): devuelve m redondeado con n decimales.

ROUND(1.456,2)

 

SIN( double n ): seno de n, el cual debe estar indicado en radianes.

SIN(2)

 

SQRT( double n ): raíz cuadrada de n.

SQRT(4)

 

UNHEX( string n ): inversa de la función HEX. Convierte la cadena dada a su formato numérico.

UNHEX(‘AB’)

 

 

Funciones de fecha


 

UNIX_TIMESTAMP(): devuelve la fecha y hora en formato UNIX epoch (número de segundos desde 1970-01-01 00:00:00 UTC).

UNIX_TIMESTAMP() -- returns 1476135611

 

UNIX_TIMESTAMP( string fecha): convierte la fecha en formato ‘yyyy-MM-dd HH:mm:ss’ a formato UNIX epoch, esto es, el número de segundo transcurridos desde 1970-01-01 00:00:00 UTC.

UNIX_TIMESTAMP('2000-01-01 00:00:00') -- returns 946713600

 

UNIX_TIMESTAMP( string fecha, string pattern ): convierte la fecha al formato indicado, y la devuelve esta en formato UNIX epoch.

UNIX_TIMESTAMP('2000-01-01 10:20:30','yyyy-MM-dd') -- returns 946713600

 

FROM_UNIXTIME( bigint number_of_seconds  [, string format] ): convierte la fecha en formato UNIX epoch al formato indicado. Por defecto ‘yyyy-MM-dd HH:mm:ss’.

FROM_UNIXTIME( UNIX_TIMESTAMP() )  -- returns the current date including the time

 

TO_DATE( string timestamp ): devuelve la fecha en formato ‘yyyy-MM-dd’.

TO_DATE('2000-01-01 10:20:30') -- returns '2000-01-01'

 

YEAR( string fecha ): devuelve el año.

YEAR('2000-01-01 10:20:30') -- returns 2000

 

MONTH( string fecha ): devuelve el mes.

MONTH('2000-03-01 10:20:30') -- returns 3

 

DAY( string fecha ), DAYOFMONTH( string fecha): devuelve el día.

DAY('2000-03-01 10:20:30') -- returns 1

 

HOUR( string fecha ): devuelve la hora.

HOUR('2000-03-01 10:20:30') -- returns 10

 

MINUTE( string fecha ): devuelve los minutos.

MINUTE('2000-03-01 10:20:30') -- returns 20

 

SECOND( string fecha ): devuelve los segundos.

SECOND('2000-03-01 10:20:30') -- returns 30

 

WEEKOFYEAR( string fecha ): devuelve el número de semana del año.

WEEKOFYEAR('2000-03-01 10:20:30') -- returns 9

 

DATEDIFF( string fecha1, string fecha2 ): devuelve el número de días entre las dos fechas.

DATEDIFF('2000-03-01', '2000-01-10') -- returns 51

 

DATE_ADD( string fecha, int dias ): suma a la fecha la cantidad indicada de días indicados.

DATE_ADD('2000-03-01', 5) -- returns '2000-03-06'

 

DATE_SUB( string fecha, int dias ): resta de la fecha la cantidad indicada de días indicados.

DATE_SUB('2000-03-01', 5) -- returns ‘2000-02-25’

 

 

Funciones de cadena


 

ASCII( string str ): convierte el primer caracter de la cadena en su valor numérico ASCII.

ASCII('hadoop') -- returns 104

ASCII('A')      -- returns 65

 

CONCAT( string str1, string str2, ... ): concatena todas las cadenas que se pasan como argumento.

CONCAT('hadoop','-','hive') -- returns 'hadoop-hive'

 

CONCAT_WS( string delimiter, string str1, string str2, … ): similar a CONCAT, pero entre las cadenas a concatenar se puede especificar el caracter que las delimitará.

CONCAT_WS('-','hadoop','hive') -- returns 'hadoop-hive'

 

FIND_IN_SET( string cadena_buscar, string lista_de_cadenas): busca la cadena cadena_buscar en lista_de_cadenas, y devuelve la posición de la primer ocurrencia. lista_de_cadenas debe estar formadas por cadenas separadas por coma.

FIND_IN_SET('ha','hao,mn,hc,ha,hef') -- returns 4

 

LENGTH( string str ): devuelve el número de caracteres de la cadena.

LENGTH('hive') -- returns 4

 

LOWER( string str ),  LCASE( string str ): convierte los caracteres de la cadena a minúsculas.

LOWER('HiVe') -- returns 'hive'

 

LPAD( string str, int n, string pad ): devuelve una cadena de n elementos, completando a la izquierda con el elementos pad hasta alcanzar la longitud indicada.

LPAD('hive',6,'v') -- returns 'vvhive'

 

LTRIM( string str ): elimina los espacios en blanco a la izquierda de la cadena.

LTRIM('   hive') -- returns 'hive'

 

REPEAT( string str, int n ): repite la cadena n veces.

REPEAT('hive',2) -- returns 'hivehive'

 

RPAD( string str, int n, string pad ): igual a LPAD, pero completando los caracteres a la derecha.

RPAD('hive',6,'v') -- returns 'hivevv'

 

REVERSE( string str ): invierte la cadena.

REVERSE('hive') -- returns 'evih'

 

RTRIM( string str ): elimina los espacios en blanco a la derecha de la cadena.

LTRIM('hive   ') -- returns 'hive'

 

SPACE( int n ): devuelve una cadena formada por n espacios en blanco.

SPACE(4) -- returns '    '

 

SPLIT( string str, string pat ): divide la cadena según el elemento pat  y devuelve un array de cadenas. Se puede especificar una expresión regular como pat.

SPLIT('hive:hadoop',':') -- returns ["hive","hadoop"]

 

SUBSTR( string str, int primer_elemento  [,int n]  ),  SUBSTRING( string str, int primer_elemento [,int n]  ): devuelve una parte de la cadena, desde primer_elemento hasta n elementos a la derecha. Si no se indica la cantidad de caracteres a tomar, se toman todos los caracteres hasta el final de la cadena.

SUBSTR('hadoop',4) -- returns 'oop'

SUBSTR('hadoop',4,2) -- returns 'oo'

 

TRIM( string str ): elimina los espacios en blanco tanto a derecha como a izquierda de la cadena.

TRIM('   hive   ') -- returns 'hive'

 

UPPER( string str ), UCASE( string str ): convierte los caracteres de la cadena a mayúscula.

UPPER('HiVe') -- returns 'HIVE'

 

 

Funciones condicionales


 

IF( condición,  bloque verdadero, bloque falso ): la sentencia IF evalúa la condición, si es verdadera devuelve el valor de bloque verdadero, caso contrario, devuelve el valor de bloque falso.

IF(1=1, 'working', 'not working') -- returns 'working'

 

COALESCE( valor1, valor2,… ): devuelve el primer valor no NULL de la lista de valores. Si todos los elementos de la lista son NULL, devuelve NULL.

COALESCE(NULL,NULL,5,NULL,4) -- returns 5

 

CASE:

CASE [ expresión ]

     WHEN condición1 THEN resultado1

     WHEN condición2 THEN resultado2

     ...

     WHEN condición_n THEN resultado_n

     ELSE resultado

END

El valor expresión es opcional y, de estar presente, se comparará en la lista de elementos condición (condición1, condición2, …, condición_n). Todos los elementos en la lista de condiciones deben ser del mismo tipo. Las condiciones serán evaluadas en el orden dado. Una vez que una condición es hallada verdadera, se ejecuta el resultado asociado a esta, y luego se sale del bloque CASE. A su vez, todos los elementos resultado deben ser del mismo tipo. En caso de que ninguna condición sea verdadera se ejecuta el bloque ELSE, el cual es opcional. Si este no se encuentra, y ninguna condición resulta verdadera, se devuelve NULL.

Ejemplo:

CASE Fruta
     WHEN 'MANZANA' THEN 'ES UNA MANZANA'
     WHEN 'NARANJA' THEN 'ES UNA NARANJA'
     ELSE 'ES OTRA FRUTA'
END

o

CASE
     WHEN Fruta = 'MANZANA' THEN 'ES UNA MANZANA'
     WHEN Fruta = 'NARANJA' THEN 'ES UNA NARANJA'
     ELSE 'ES OTRA FRUTA'
END

 

Comentarios