Vamos a bajar ahora a tierra las ideas que mencionamos en la sección anterior. Para eso vamos a utilizar una implementación de BigTable en java, opensource y gratuita llamada Apache HBase.
Lo primero que necesitamos para trabajar con HBase, es lógicamente, tener HBase, así que
No vamos a entrar en detalle en el entorno de trabajo, asumimos acá que ya trabajan con java + eclipse + maven.
Entonces, tenemos que crear un proyecto maven y configurar el pom.xml con las siguientes dos cosas:
Dependencia a hbase:
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase</artifactId>
<version>0.90.2</version>
</dependency>
Repositorio maven adicional (para obtener una dependencia transitiva)
<repositories>
<repository>
<id>thrift-repo</id>
<url>http://people.apache.org/~psmith/hbase/repo</url>
</repository>
</repositories>
Código Java
Lo primero que vamos a necesitar para trabajar con nuestras tablas, es, lógicamente, crearlas. Esto se puede hacer desde una aplicación cliente de HBase, es decir, desde código java mismo, a través de las API's que nos provee. La creación de tablas es considerada una operación de "administración".
Lo que vamos a hacer es:
Vemos un poco el código acá.
Creamos una instancia de HBaseAdmin utilizando un objeto de tipo HBaseConfiguration. A este último le seteamos el nombre del master host al cual conectarse.
Configuration config = HBaseConfiguration.create();
config.set("hbase.zookeeper.quorum", "vitalogy");
return new HBaseAdmin(config);
El HBaseAdmin es un facade que nos permite realizar operaciónes de administrador sobre el servidor, como crear tablas, dropear, etc.
admin.createTable(new HTableDescriptor("personas"));
admin.disableTable("personas");
admin.addColumn("personas", new HColumnDescriptor("dni"));
admin.addColumn("personas", new HColumnDescriptor("nacimiento"));
admin.enableTable("personas");
Así creamos una nueva tabla "personas". Luego la deshabilitamos (ya que es la única forma de modificar la estructura), y creamos las columnas.
Herramientas de monitoreo
Antes de correr el ejemplo para crear las tablas, vamos a ver dos herramientas básicas que nos da HBase para interactuar y ver el estado:
A medida que sigamos con el ejemplo vamos a jugar un poquito más con estas herramientas.
Ejecutando el ejemplo
Entonces, vamos a crear nuestras tablas. Para eso ejecuta el main()
No pasa nada loco. Vemos en la consola algunas lineas relevantes de log:
11/05/15 14:52:05 INFO client.HBaseAdmin: Started disable of personas
11/05/15 14:52:07 INFO client.HBaseAdmin: Disabled personas
11/05/15 14:52:07 INFO client.HBaseAdmin: Started enable of personas
11/05/15 14:52:09 INFO client.HBaseAdmin: Enabled table personas
Ahora vamos entonces al shell y ejecutamos list. En este caso vemos que lista la nueva tabla:
TABLE
personas
1 row(s) in 0.1240 seconds
Insertando filas a la tabla
Ahora, lógicamente queremos comenzar a persistir información en la nueva tabla. Entonces veamos un nuevo ejemplo de esto en código:
HTable table = new HTable(HBaseConfiguration.create(), "personas");
Put putRow = new Put(Bytes.toBytes("anibal"));
putRow.add(Bytes.toBytes("nacimiento"), Bytes.toBytes("nacimiento"), Bytes.toBytes("28/02/1980"));
putRow.add(Bytes.toBytes("dni"), Bytes.toBytes("dni"), Bytes.toBytes("28.438.123"));
table.put(putRow);
Ejecutemos, y veamos que sucede, No hay logs al respecto (probablemente se puede aumentar el nivel de verbosity del log)
Consultando por el Shell: 'count', 'scan' y 'get'
Vamos a ver qué pasó, usando el shell.
> count 'personas'
1 row(s) in 0.0640 seconds
"Count" es un comando muy parecido al viejo "count" de SQL. Nada mágico, solo indica la cantidad de filas que tiene la tabla "personas".
Ahora, obviamente, queremos obtener más información que esto, asi que para esto, vamos a ver un nuevo comando llamado "scan". Este, sirve para hacer consultas sobre varias "rows" al mismo tiempo. Es decir, no es para obtener un único valor, sino para justamente "scannear" alguna sección específica de nuestro mapa.
Dicho sea de paso, se puede obtener ayuda para cada comando a través del mismo shell con:
> help 'scan'
donde pueden reemplazar 'scan' por cualquier nombre de comando.
Ejecutamos entonces:
> scan 'personas'
ROW COLUMN+CELL
anibal column=dni:dni, timestamp=1305484695835, value=28.438.123
anibal column=nacimiento:nacimiento, timestamp=1305484695835, value=28/02/1980
1 row(s) in 0.0600 seconds
Voilà ! Ahí tenemos nuestro "anibal" con los datos ingresados.
Fíjense ahí que figura dos celdas especiales:
Por último, vamos a ver un tercer comando, de paso, para hacer consultas. El "get".
> get 'personas', 'anibal'
COLUMN CELL
dni:dni timestamp=1305484695835, value=28.438.123
nacimiento:nacimiento timestamp=1305484695835, value=28/02/1980
2 row(s) in 0.0840 seconds
(Atentos a la coma ',' entre los parámetros, puede traerles un dolor de cabeza el olvidárselas :)
Consultando desde Java
Todo esto que hicimos desde el shell, es posible hacerlo desde nuestra aplicación java. Lógicamente, porque no tendría sentido que la aplicación no pueda hacer consultas :)
Entonces, veamos un tercer ejemplo de código.
Vemos entonces, como hacer un "Get" y como hacer un "Scan".
Borrando rows
Ahora vamos a ver comandos "destructivos".
Primero, como borrar rows.
Es bastante simple, y la misma idea que antes,
HTable table = new HTable(HBaseConfiguration.create(), "personas");
Delete delete = new Delete(Bytes.toBytes("anibal"));
table.delete(delete);
Podemos hacer esto mismo desde el shell.
> delete 'personas', 'anibal'
0 row(s) in 0.4810 seconds
Dropeando tablas
Por último, vamos a eliminar completamente la tabla. Esto es, como antes, una operación de adminsitración, o en realidad de "estructura". Por esto es parte del grupo de comandos llamados "ddl".
La forma de hacer esto a través del API java es:
HBaseAdmin admin = CreatePersonasTable.connectToAdmin();
admin.disableTable("personas");
admin.deleteTable("personas");
Y la forma de hacer esto por shell es:
> disable 'personas'
0 row(s) in 2.1740 seconds
> drop 'personas'
0 row(s) in 1.5880 seconds