Mostrando entradas con la etiqueta HBase. Mostrar todas las entradas
Mostrando entradas con la etiqueta HBase. Mostrar todas las entradas

viernes, 21 de noviembre de 2014

[HBase] ERROR org.apache.hadoop.hbase.regionserver.HRegionServerCommandLine: Region server exiting

Apache HBase

Problema: ERROR org.apache.hadoop.hbase.regionserver.HRegionServerCommandLine: Region server exiting

bash# tail -f /var/log/hbase/hbase-cmf-hbase-REGIONSERVER-servername.log.out
...
2014-10-18 17:02:14,048 ERROR org.apache.hadoop.hbase.regionserver.HRegionServerCommandLine: Region server exiting
java.lang.RuntimeException: HRegionServer Aborted
at org.apache.hadoop.hbase.regionserver.HRegionServerCommandLine.start(HRegionServerCommandLine.java:66)
at org.apache.hadoop.hbase.regionserver.HRegionServerCommandLine.run(HRegionServerCommandLine.java:85)
at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:70)
at org.apache.hadoop.hbase.util.ServerCommandLine.doMain(ServerCommandLine.java:126)
at org.apache.hadoop.hbase.regionserver.HRegionServer.main(HRegionServer.java:2320)
2014-10-18 17:02:14,049 INFO org.apache.hadoop.hbase.regionserver.ShutdownHook: Shutdown hook starting; hbase.shutdown.hook=true; fsShutdownHook=org.apache.hadoop.fs.FileSystem$Cache$ClientFinalizer@66a3e2e0
2014-10-18 17:02:14,049 INFO org.apache.hadoop.hbase.regionserver.HRegionServer: STOPPED: Shutdown hook
2014-10-18 17:02:14,049 INFO org.apache.hadoop.hbase.regionserver.ShutdownHook: Starting fs shutdown hook thread.
2014-10-18 17:02:14,052 INFO org.apache.hadoop.hbase.regionserver.ShutdownHook: Shutdown hook finished.

Solución: Revisar que las fechas (date) en los servidores, master & region, de HBase se encuentren sincronizados.

En caso de disponer del servicio ntpd, bastará con reiniciarlo.
bash# service ntpd restart
En caso de encontrarnos en un entorno el cual no tiene salida a internet directa, es decir, nuestros servidores se encuentren detrás de un proxy, deberemos:
  • Asegurarnos que el proxy/firewall permite el tráfico UDP para poder sincronizar con los servidores de NTP externos.
  • Configurar un servidor de NTP interno con el cual poder sincronizar nuestros servidores:
bash# ntpdate <ip_NTP_server>
  • Solución cutre, pero totalmente válida:
bash# DATE_STR="$(curl -sD - google.com | grep ^Date: | cut -d' ' -f3-6)Z"; date -s "$DATE_STR"

miércoles, 2 de abril de 2014

[HowTo] Use the HBase Thrift Interface

HowTo Use the HBase Thrift Interface
Siguiendo con la temática de la anterior entrada "[HowTo] Instalar Apache Thrift Server y RHBase" hoy comparto unos enlaces a unos más que interesantes artículos o tutoriales del Blog de Cloudera, del que os recomiendo encarecidamente su seguimiento y lectura, sobre el acceso a los datos en HBase a través del interfaz facilitado por el software Apache Thrift.
Por mi parte trataré de ir actualizando esta entrada según vayan publicando nuevas entregas acerca de esta temática.

Espero que sean de vuestro interés.

martes, 1 de abril de 2014

[HowTo] Instalar Apache Thrift Server y RHBase


Esta claro que el principal objetivo de cualquier sistema Big Data es recoger y poder almacenar una gran cantidad de información para consultarla en un futuro con rapidez. Pero... ¿por qué olvidarnos de su posterior análisis o tratamiento? Este puede enriquecer más si cabe nuestros sistemas o darnos una visión nueva de negocio para nada despreciable.


Sobre lo primero ya vimos como importar información de nuestras bases de datos MySQL a nuestro nuevo sistema de Big Data en la anterior entrada "HBase - Importar Datos (SQOOP)".

Mientras que de la segunda parte, de la necesidad de estudio de la información, es de donde surge esta entrada. Es muy factible que antes o después nos soliciten analizarla bien a nuestro equipo o bien que pongamos a disposición de terceros las herramientas necesarias.


R es un lenguaje y entorno para la computación estadística y gráfica. R provee una amplia variedad de técnicas entre las que se encuentra el análisis de time-series, razón que será la principal para su uso en mi organización.

Bien, centrémonos a continuación ya en el asunto que pretende cubrir esta entrada.


RHBase se trata de una librería R cuyo principal objetivo es comunicarse con HBase. Dicho paquete nos permitirá 'jugar' con la información almacenada en esta NoSQL.



Entre las funcionalidades básicas que RHBase nos ofrece están:
  • Manipulación de Tablas: hb.new.table, hb.delete.table, hb.describe.table, hb.set.table.mode, hb.regions.table, hb.list.tables
  • Lectura/Escritura: hb.insert, hb.get, hb.delete, hb.insert.data.frame, hb.get.data.frame, hb.scan, hb.scan.ex
  • Otras: hb.defaults, hb.init

Bien, a continuación detallaré los pasos que dí para lograr instalar RHBase. Anotar que el sistema del que parto es CentOS 6.4 (x86_64) y en él se ha instalado previamente Cloudera 4.8.1 y R (ver HowTo Instalar R, RHadoop y RStudio).

Apache Thrift
En su propia web se nos facilita una serie de prerrequisitos para diferentes sistemas operativos. Os dejo el enlace para los de CentOS, aunque al menos a mí me resultaron insuficientes.
  1. Openssl-devel. Paquete necesario para obtener la librería libcrypto.
      # yum install openssl-devel.x86_64 -y
  2. Autoconf. Versión mínima requerida 2.65 ó superior.
      # wget http://ftp.gnu.org/gnu/autoconf/autoconf-latest.tar.gz
      # tar xvzf autoconf-latest.tar.gz
      # cd autoconf-2.69/
      # ./configure
      # make
      # make check                   (tarda bastante)
      # make install
    
  3. Resto de Dependencias CentOS.
      # yum install automake flex bison pkgconfig gcc-c++ libevent-devel zlib-devel python-devel ruby-devel -y
    
    Es posible que durante la instalación del paquete Automake se observe como se selecciona e instala como una dependencia más la librería autconf-2.63-5.1.el6.noarch, no preocuparse, no supondrá ningún problema de cara al futuro. Aún así, tras finalizar la instalación de todos estos paquetes podremos verificar la versión del mismo ejecutando el siguiente comando:
      # autoconf -V
        autoconf (GNU Autoconf) 2.69
        Copyright (C) 2012 Free Software Foundation, Inc.
        License GPLv3+/Autoconf: GNU GPL version 3 or later
        <http://gnu.org/licenses/gpl.html>, <http://gnu.org/licenses/exceptions.html>
        This is free software: you are free to change and redistribute it.
        There is NO WARRANTY, to the extent permitted by law.
        Written by David J. MacKenzie and Akim Demaille.
    
  4. Boost (69,5 MB):
      # wget http://sourceforge.net/projects/boost/files/boost/1.55.0/boost_1_55_0.tar.gz/download
      # tar xvzf boost_1_55_0.tar.gz
      # cd boost_1_55_0
      # ./bootstrap.sh
        Building Boost.Build engine with toolset gcc... tools/build/v2/engine/bin.linuxx86_64/b2
        Detecting Python version... 2.6
        Detecting Python root... /usr
        Unicode/ICU support for Boost.Regex?... not found.
        Generating Boost.Build configuration in project-config.jam...
    
        Bootstrapping is done. To build, run:
    
        ./b2  
    
        To adjust configuration, edit 'project-config.jam'.
        Further information:
    
        - Command line help:
          ./b2 --help
    
        - Getting started guide:
          http://www.boost.org/more/getting_started/unix-variants.html
        - Boost.Build documentation:
          http://www.boost.org/boost-build2/doc/html/index.html
    
      # ./b2              (tardará bastante en finalizar su ejecución)
        ...
        The Boost C++ Libraries were successfully built!
    
        The following directory should be added to compiler include paths:
            /root/software/boost_1_55_0
        The following directory should be added to linker library paths:
            /root/software/boost_1_55_0/stage/lib
    
      # ./bjam --prefix=/usr/local/ link=static runtime-link=static stage install
        ...
        common.copy /usr/local/include/boost/tr1/tr1/unordered_map
        ...updated 11321 targets...
    
    Podremos verificar la existencia de estas librerías:
      # ls -al /usr/local/lib/libboost_*
    
  5. Libtool. Paquete necesario para obtener la librería libtoolize.
      # yum install libtool-2.2.6-15.5.el6.x86_64 -y
    
  6. Thrift. Podemos obtener el paquete mediante dos formas:
    Opción 1) Desde su propia web nos descargamos una de sus versiones:
      # wget http://archive.apache.org/dist/thrift/0.8.0/thrift-0.8.0.tar.gz
      # tar xvzf thrift-0.8.0.tar.gz
      # cd thrift-0.8.0
    
    Opción2) 'Clonamos' el proyecto:
      # git clone https://git-wip-us.apache.org/repos/asf/thrift.git thrift
      # cd thrift
      # ./bootstrap.sh          (si elegimos esta segunda opción este paso es necesario)
    
    Yo opté por la primera. A partir de aquí los siguientes pasos son idénticos para ambas opciones.
      # ./configure --with-boost=/usr/local
      # make
      # make check                   (asegurarse que el puerto 9090 esté libre, por ejemplo asegurarse que el servicio hbalse =>hbasethriftserver de cloudera esté detenido en caso de haberse instalado/habilitado)
      # make install
      # cp /usr/local/lib/libthrift-0.8.0.so /usr/lib/
      # /sbin/ldconfig /usr/lib/libthrift-0.8.0.so
    

    A continuación deberemos añadir la siguiente variable de entorno a nuestro ficheros:

    /root/.bashrc => EXPORT PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/
    /etc/profile => EXPORT PKG_CONFIG_PATH=/usr/local/lib/pkgconfig/
      # source /root/.bashrc
      # source /etc/profile
    
    Verificar el resultado del siguiente comando:
      # pkg-config --cflags thrift
        -I/usr/local/include/thrift
    
  7. RHBase:
      # wget https://raw.github.com/RevolutionAnalytics/rhbase/master/build/rhbase_1.2.0.tar.gz
      # R CMD INSTALL rhbase_1.2.0.tar.gz
        * installing to library ‘/usr/lib64/R/library’
        * installing *source* package ‘rhbase’ ...
        ** libs
        g++ -m64 -I/usr/include/R -DNDEBUG  -I/usr/local/include   -I. -g  -DHAVE_UINTPTR_T -DHAVE_NETDB_H=1 -fpermissive -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -I./gen_cpp `pkg-config --cflags thrift` -Wall -fpic  -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic  -c Hbase.cpp -o Hbase.o
        g++ -m64 -I/usr/include/R -DNDEBUG  -I/usr/local/include   -I. -g  -DHAVE_UINTPTR_T -DHAVE_NETDB_H=1 -fpermissive -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -I./gen_cpp `pkg-config --cflags thrift` -Wall -fpic  -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic  -c Hbase_constants.cpp -o Hbase_constants.o
        g++ -m64 -I/usr/include/R -DNDEBUG  -I/usr/local/include   -I. -g  -DHAVE_UINTPTR_T -DHAVE_NETDB_H=1 -fpermissive -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -I./gen_cpp `pkg-config --cflags thrift` -Wall -fpic  -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic  -c Hbase_types.cpp -o Hbase_types.o
        g++ -m64 -I/usr/include/R -DNDEBUG  -I/usr/local/include   -I. -g  -DHAVE_UINTPTR_T -DHAVE_NETDB_H=1 -fpermissive -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H -I./gen_cpp `pkg-config --cflags thrift` -Wall -fpic  -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m64 -mtune=generic  -c tools.cc -o tools.o
        g++ -m64 -shared -L/usr/local/lib64 -o rhbase.so Hbase.o Hbase_constants.o Hbase_types.o tools.o -L/usr/local/lib -lthrift -L/usr/lib64/R/lib -lR
        installing to /usr/lib64/R/library/rhbase/libs
        ** R
        ** inst
        ** preparing package for lazy loading
        ** help
        *** installing help indices
         converting help for package ‘rhbase’
         finding HTML links ... done
          admin               html
          functions           html
          rhbase              html
        ** building package indices
        ** testing if installed package can be loaded
        * DONE (rhbase)
        Making 'packages.html' ... done
    
    Verificar que existe /usr/lib64/R/library/rhbase/
  8.   # ls -al /usr/lib64/R/library/rhbase/
        total 48
        drwxr-xr-x  9 root root 4096 mar 17 14:48 .
        drwxr-xr-x 49 root root 4096 mar 17 14:48 ..
        -rw-r--r--  1 root root  461 mar 17 14:48 DESCRIPTION
        drwxr-xr-x  2 root root 4096 mar 17 14:48 help
        drwxr-xr-x  2 root root 4096 mar 17 14:48 html
        -rw-r--r--  1 root root  222 mar 17 14:48 INDEX
        drwxr-xr-x  2 root root 4096 mar 17 14:48 libs
        drwxr-xr-x  2 root root 4096 mar 17 14:48 Meta
        -rw-r--r--  1 root root   41 mar 17 14:48 NAMESPACE
        drwxr-xr-x  2 root root 4096 mar 17 14:48 R
        drwxr-xr-x  2 root root 4096 mar 17 14:48 samples
        drwxr-xr-x  2 root root 4096 mar 17 14:48 unitTests
    
  9. Iniciar el servicio HBase Thrift Server
      # hbase thrift start
        ...INFO thrift.ThriftServerRunner: starting TBoundedThreadPoolServer on /0.0.0.0:9090; min worker threads=16, max worker threads=1000, max queued requests=1000
        ...
    
  10. R
      # R
      R version 3.0.2 (2013-09-25) -- "Frisbee Sailing"
      Copyright (C) 2013 The R Foundation for Statistical Computing
      Platform: x86_64-redhat-linux-gnu (64-bit)
      ...
    
      > require(rhbase)
      Loading required package: rhbase
    
      > hb.init();
      <pointer: 0x1ec4030="">
      attr(,"class")
      [1] "hb.client.connection"
    
      > hb.list.tables()
      $`test-table`
    
      maxversions compression inmemory bloomfiltertype bloomfiltervecsize bloomfilternbhashes
      cf:           3        NONE    FALSE            NONE       0       0
    
      blockcache timetolive
      cf:      FALSE         -1
    
    ¡¡¡ IMPORTANTE !!! En caso de leer una tabla cuyos datos son caracteres, debemos inicializar la conexión de la siguiente forma:
      > hb.init(serialize="character")
      <pointer: 0x306a2f0="">
      attr(,"class")
      [1] "hb.client.connection"
    
      > hb.get (tablename="TABLENAME", rows="ROWKEY", colspec="COLUMNFAMILY:")
      [[1]]
      [[1]][[1]]
      [1] "ROWKEY"
    
      [[1]][[2]]
      [1] "cf:ATTR1_CADENA"     "cf:ATTR2_INT"        "cf:ATTR3_INT"        "cf:ATTR4_INT"    "cf:ATTR5_CADENA" "cf:ATTR6_INT"    
    
      [[1]][[3]]
      [[1]][[3]][[1]]
      [1] "BOTH"
    
      [[1]][[3]][[2]]
      [1] "62"
    
      [[1]][[3]][[3]]
      [1] "143"
    
      [[1]][[3]][[4]]
      [1] "10455"
    
      [[1]][[3]][[5]]
      [1] "CADENA"
    
      [[1]][[3]][[6]]
      [1] "24"
    
      > quit();
      Save workspace image? [y/n/c]: y
    

lunes, 31 de marzo de 2014

HBase - Importar Datos (SQOOP)


Probablemente una de las primeras cosas que tengamos que hacer tras implantar un sistema de Big Data, en mi caso Cloudera 4.8.1, será importar todos o buena parte de los datos de nuestros diversos sistemas de información.

Cloudera nos facilita diversos proyectos dentro de su ecosistema con los que trabajar y volcar esta información.


El primero que me gustaría presentaros es Apache HBase. Se trata de la "base de datos" de Hadoop, un sistema de almacenamiento de datos totalmente distribuido y escalable. Digo "base de datos" porque HBase realmente es lo que se conoce como una NoSQL, es decir, una base de datos no relacional en las que los datos almacenados no requieren de una estructura fija como hasta ahora ha venido sucediendo con las tradicionales bases de datos relacionales (RDBMS).

La aparición de estas NoSQL surgió de la necesidad por las grandes compañías (Google, Amazon...) de premiar el rendimiento frente a la coherencia de los datos, tarea en la que las tradicionales bases de datos invierten una gran cantidad de tiempo y recursos del sistema.

Así pues, podríamos decir que una NoSQL encaja a la perfección cuando la finalidad de nuestro proyecto es el almacenamiento y tratamiento de enormes tablas, con enormes me refiero a tablas de billones de filas por millones de columnas.

Lógicamente no vamos a tener que introducir toda esta cantidad de información a mano, sería un infierno hacerlo, así que llegados a este punto surge la necesidad de conocer como volcar toda o parte de la información almacenada en un tercer sistema.

En esta ocasión voy a explicar como importar datos de una MySQL pues seguramente muchos de los orígenes de nuestras fuentes de datos vayan a ser éstas.
Aquí es donde hace acto de presencia otra de las herramientas del ecosistema, SQOOP, herramienta que nos facilitará esta tarea y que a su vez utiliza mapreduce, una de las dos características que definen a un sistema Hadoop, para la importación de los datos.

Sqoop también permite la acción contraria, exportación de los mismos.

Antes de empezar deberemos asegurarnos que existen las variables de entorno $HBASE_HOME y $SQOOP_HOME, aunque bueno, en caso de no existir alguna de ellas el comando sqoop fallará, teniendo que definirlas:
 # export $HBASE_HOME = /opt/cloudera/parcels/CDH-4.5.0-1.cdh4.5.0.p0.30/lib/hbase
 # export $SQOOP_HOME = /opt/cloudera/parcels/CDH-4.5.0-1.cdh4.5.0.p0.30/lib/sqoop

Caso 1: Importar Tabla con Primary Key

Este ejemplo importará todos los datos, filas y columnas, de la tabla <tableMySQL> de la base de datos <db> ubicada en el servidor <host> en la <tableHBase> y column-family <cf1>. Además, el usuario <user> con contraseña <passwd> deberá tener configurados los privilegios/permisos necesarios.
 # $SQOOP_HOME/sqoop import --connect jdbc:mysql://<host>/<db> --username <user> --password <passwd> --table <tableMySQL> --hbase-table <tableHBase>  --column-family <cf1> --hbase-create-table
El argumento hbase-create-table creará la tabla <tableHBase> en caso de no existir.

Caso 2: Importar Tabla sin Primary Key

Ahora bien, si la tabla origen carece de primary key, deberemos decirle nosotros a Sqoop como deberá construir la rowkey de la tabla HBase.

Para ello usaremos el argumento hbase-row-key que constará del nombre de una o más columnas de la tabla MySQL, <column1,column2,columnN>.
 # $SQOOP_HOME/sqoop import --connect jdbc:mysql://<host>/<db> --username <user> --password <passwd> --table <tableMySQL> --hbase-table <tableHBase> --column-family <cf1> --hbase-row-key <column1,column2,columnN> --hbase-create-table
En caso de haber coincidencias en la rowkey NO se crearán diferentes entradas/filas en HBase, sino una única, pues la rowkey será idéntica. Otra cosa es que HBase almacenará el valor previo como lo que se conoce como version.

El número de versiones para cada celda que por defecto HBase almacena es 3.

De paso sea dicho, NO  penséis en modificar este valor a digamos infinito para tener un histórico de los valores. Esto es totalmente desaconsejable y afectará al rendimiento de vuestra plataforma.

Para solucionarlo o bien pensamos en incluir la fecha como parte de nuestra rowkey o implementamos lo que se conoce como time-series database. Un ejemplo de esto último sería el proyecto de monitorización OpenTSDB, 

Caso 3: Importar algunas columnas

No siempre querremos importar todas las columnas de una tabla así que podremos limitarlo gracias al argumento columns de la siguiente manera:
 # $SQOOP_HOME/sqoop import --connect jdbc:mysql://<host>/<db> --username <user> --password <passwd> --table <tableMySQL> --hbase-table <tableHBase> --columns <column1,column5,column10> --column-family <cf1> --hbase-row-key <column1> --hbase-create-table
Ahora bien, deberemos asegurarnos que la columna que vayamos a usar como rowkey deba estar incluida en la lista de columnas a importar, de otro modo Sqoop finalizará satisfactoriamente, pero no grabará nada en HBase.

Caso 4: Consulta SQL

Sqoop también nos permite importar el resultado de una sentencia SQL. Esto lo conseguiremos gracias al argumento query que nos permitirá definir dicha consulta tal cual lo hacemos en el lenguaje habitual de SQL. En caso de declararlo ya no será necesario incluir el argumento table.

La única limitación o más bien obligación que existe es incluir en ella la siguiente cláusula: where $CONDITIONS.
 # $SQOOP_HOME/sqoop import --connect jdbc:mysql://<host>/<db> --username <user> -password <passwd> --query 'select * from tablaMySQL where $CONDITIONS and column5 > 10' --split-by <column1> --hbase-create-table --hbase-table <tableHBase> --hbase-row-key <column1,column5,column10> --column-family <cf1>
Bueno, en caso de usar comillas dobles para declarar el argumento query debido a que en la consulta SQL hagamos uso de las comillas simples, deberemos escapar el carácter '$' de $CONDITIONS => \$CONDITIONS. Por ejemplo:
 # $SQOOP_HOME/sqoop import --connect jdbc:mysql://<host>/<db> --username <user> -password <passwd> --query "select * from tablaMySQL where \$CONDITIONS and column5 > 10 and column1 like ''" --split-by <column1> --hbase-create-table --hbase-table <tableHBase> --hbase-row-key <column1,column5,column10> --column-family <cf1>




Pues hasta aquí llega este breve tutorial acerca de cómo importar datos de una MySQL en HBase.

En caso de necesitar mayor información os remito a la siguiente guía: User Sqoop Guide; O al libro Apache Sqoop Cookbook (100% recomendable).