Estas en: Home > sql

Entradas etiquetadas con sql

Logo Cassandra

Cassandra 2.x y PHP para desarrolladores SQL: Instalación

0

La base de datos No-SQL Cassandra fue creada por Facebook a causa de la necesidad de disponer de una base de datos distribuida de alto rendimiento, flexible, tolerante a fallos, escalable y que fuese capaz de procesar grandes cantidades de datos. Más tarde fue liberada bajo licencia Apache y actualmente es utilizada principalmente por empresas de internet con proyectos con un alto uso de base de datos como Twitter.

En esta serie de artículos iré desgranando la instalación, funcionamiento y desarrollo de aplicaciones en PHP con Cassandra, comparando las sentencias utilizadas para insertar, actualizar, etc de SQL con los métodos a utilizar en Cassandra. Por desgracia al ser algo completamente distinto a cualquier base de datos SQL tendré que añadir algo de teoría, pero intentaré que os resulte lo más ameno posible.

Al toro.

REQUISITOS

Para la realización de esta guía se utilizará Debian 8 Jessie como sistema operativo.

Doy por hecho que ya se dispone de un servidor web Apache con PHP instalado en la máquina de testeo que se esté usando. Las aplicaciones que se van a instalar han sido probadas en una máquina virtual Debian 8 Jessie utilizando como aplicación de virtualización VirtualBox, instalado en un host Debian 8 Jessie.

En un servidor de producción recomiendo que tenga bastante RAM (por encima de 1GB, ya veremos más adelante el porqué. En la máquina virtual que uso de testeo dispone de 700 MB y funciona bien, pero en producción no es lo recomendable).

Instalaremos la base de datos Cassandra y PHP-Driver que nos dará la extensión para PHP y una abstracción de la base de datos donde tenemos los métodos básicos para trabajar con Cassandra: insertar, actualizar, borrar, crear, etc.

PREPARANDO EL SISTEMA

Antes de empezar a instalar debemos actualizar el sistema operativo de la forma habitual:

apt-get update
apt-get upgrade

Una vez actualizado el sistema empezamos a instalar.

INSTALANDO CASSANDRA

Lo primero que necesitamos hacer para instalar Cassandra es editar los repositorios de Debian:

nano /etc/apt/sources.list

Una vez que se abra el editor añadimos las siguientes lineas:

deb http://www.apache.org/dist/cassandra/debian/ 21x main
deb-src http://www.apache.org/dist/cassandra/debian/ 21x main

Como podrás observar después de la ruta del repositorio se ha añadido “21x” esto indica el número de versión a obtener, en este caso es la versión actual de cassandra al crear este post. No se indica el número de parche, es decir, actualmente se puede descargar Cassandra 2.1.

Si dentro de unos meses sale la versión “2.2” solo tendrás que cambiar el uno por el dos.
Volvemos a consola y actualizamos los repositorios.

apt-get update

Nos dará un error en las claves gpg. Procedemos a actualizarlas con las siguientes instrucciones:

gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D
gpg --export --armor F758CE318D77295D | sudo apt-key add -

Ojo con el guión del final, hay que añadirlo, sino dará error.

Con el paquete 0.7.5 nos da otro error de clave gpg así que también instalamos esta de la misma manera:

gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00
gpg --export --armor 2B5C1B00 | sudo apt-key add -

También necesitarás añadir la siguiente clave:

gpg --keyserver pgp.mit.edu --recv-keys 0353B12C
gpg --export --armor 0353B12C | sudo apt-key add -

Verificamos que tenemos el sistema actualizado.

apt-get update
apt-get upgrade

Actualizamos todos los paquetes que aparezcan.

Procedemos a instalar el paquete de la base de datos NoSQL Cassandra:

apt-get install cassandra

Cassandra necesita Java para funcionar. Debian 8 ya dispone de OpenJDK en su versión 7, y aunque desde los desarrolladores de Cassandra no recomiendan su uso, para los ejemplos que vamos a desarrollar nos sirve.

En producción, o si vas a desarrollar un proyecto con Cassandra tendrás que instalar la última versión de Java de Oracle.

Por último, ejecutamos el siguiente comando para construir las dependencias:

dpkg-buildpackage -uc -us

Si el sistema no te reconoce el comando es porque te falta el paquete dpkg-dev. Instálalo de la forma habitual, y vuelve a intentarlo:

apt-get install dpkg-dev

INSTALANDO DATASTAX PHP-DRIVER PARA CASSANDRA

Datastax PHP driver, es el controlador y abstracción de base de datos que utilizaremos para conectar con Cassandra desde PHP. Este controlador nos da la posibilidad de trabajar tanto con CQL (Cassandra Query Language. Parecido a SQL) y/o el protocolo binario de Cassandra.

Aunque en la página del repositorio nos indican varias formas de instalar el controlador (https://github.com/datastax/php-driver/blob/master/ext/README.md), el único que me ha funcionado correctamente ha sido el de descargar las fuentes y compilarlo. Tú puedes probar los otros métodos, pero el que te voy a indicar funciona en Debian 8.

Las siguientes instrucciones deberías ejecutarlas en el ordenador de desarrollo y no en el servidor o máquina virtual donde tengas instalada la base de datos. (A no ser que la hayas instalado en el ordenador de desarrollo).

Instalamos algunos paquetes necesarios para realizar la compilación:

apt-get install g++ make cmake libuv-dev libssl-dev libgmp-dev php5 php5-dev openssl libpcre3-dev git

Primero necesitamos descargar las fuentes desde GitHub, utiliza el directorio que prefieras:

git clone https://github.com/datastax/php-driver.git
cd php-driver
git submodule update --init
cd ext
./install.sh

Estos comandos nos ha creado un archivo llamado cassandra.so en /usr/lib/php5/20131226/ (el número del directorio puede variar en tu instalación. Revísalo).
Ahora creamos un archivo .ini para la extensión de PHP:

nano /etc/php5/mods-available/cassandra.ini

Dentro de ese archivo añadimos las siguientes líneas:

; configuration for PHP driver Cassandra
extension=cassandra.so

Guardamos.

Le indicamos a PHP que nos active la extensión

php5enmod cassandra

Y reiniciamos Apache:

/etc/init.d/apache2 restart

Ahora si ejecutamos el siguiente comando para mostrar los módulos de PHP debería aparecernos Cassandra, si no es así es que algo a fallado:

php -m

INICIANDO CASSANDRA POR PRIMERA VEZ

Ahora que ya tenemos todo instalado es el momento de arrancar Cassandra. Esto es algo muy sencillo, solo tienes que ejecutar el siguiente comando:

cassandra -f

También tienes otras maneras de iniciar Cassandra. Por ejemplo como servicio:

service cassandra start

Si al iniciar Cassandra te da un error de memoria, haz lo siguiente:

Accede a /etc/cassandra y edita el archivo cassandra-env.sh:

cd /etc/cassandra
nano cassandra-env.sh

Busca las siguientes dos líneas:

#MAX_HEAP_SIZE="4G"
#HEAP_NEWSIZE="800M"

Descomenta las dos líneas, y sustituye los valores por unos más bajos. En mi caso he bajado MAX_HEAP_SIZE a 2G y HEAP_NEWSIZE lo he dejado como está.

Estas dos líneas permiten configurar la cantidad de memoria RAM que Cassandra utilizará.

Ahora vamos a utilizar el código de ejemplo que hay en el repositorio de PHP-Driver para probar que todo funciona correctamente.

Crea un archivo PHP con el siguiente contenido:

  1. <?php
  2. $cluster = Cassandra::cluster() // connects to localhost by default
  3. ->build();
  4. $keyspace = 'system';
  5. $session = $cluster->connect($keyspace); // create session, optionally scoped to a keyspace
  6. $statement = new Cassandra\SimpleStatement( // also supports prepared and batch statements
  7. 'SELECT keyspace_name, columnfamily_name FROM schema_columnfamilies'
  8. );
  9. $future = $session->executeAsync($statement); // fully asynchronous and easy parallel execution
  10. $result = $future->get(); // wait for the result, with an optional timeout
  11.  
  12. foreach ($result as $row) { // results and rows implement Iterator, Countable and ArrayAccess
  13. printf("The keyspace %s has a table called %s\n", $row['keyspace_name'], $row['columnfamily_name']);
  14. }

Este código devuelve las tablas que contiene el Keyspace “system” (Más adelante explicaré que es eso). Si te da error como este: “No hosts available for the control connection”, puede ser por dos razones, o bien no está funcionando Cassandra, con lo que tendrás que iniciarla con uno de los comandos anteriores, o bien no la tienes en localhost sino en un servidor externo o máquina virtual.

Para resolverlo tendrás que sustituir las siguientes líneas:

  1. <?php
  2. $cluster = Cassandra::cluster() // connects to localhost by default
  3. ->build();

Por estas otras:

  1. <?php
  2. $cluster = Cassandra::cluster()
  3. ->withContactPoints('127.0.0.1')
  4. ->build();

Sí, solo añadimos “->withContactPoints(‘127.0.0.1’)”, con este método le estamos indicando la ip de nuestro servidor. En tu caso es posible que tengas que sustituir “127.0.0.1” por la ip de tu servidor o máquina virtual. Más adelante explicaré cada método, pero para verificar que está funcionando todo correctamente es suficiente.

 

Con esto finalizamos la instalación de Cassandra para que pueda ser utilizada por PHP.

Ebooks de desarrollo gratuitos

0

Al final, por mucho contenido que haya en internet, los desarrolladores terminamos tirando de libros. Por suerte para nuestros bolsillos hay páginas que nos ofrecen muchos conocimientos comprimidos en un ebook, como es el caso que os traigo hoy.

En esta web encontraréis una decena de  ebooks de desarrollo, desde SQL Server a Ensamblador, pasando por Windows Store, F#, Git, jQuery, etc.

Disfrutadlo, y recordad: el conocimiento os hará libres.

http://www.syncfusion.com/resources/techportal/ebooks?utm_medium=devmediaebOct13

Logo Cassandra

Cassandra 1.x y PHP para desarrolladores SQL: Clusters

2

Cassandra permite crear anillos o clusters de servidores de una forma muy sencilla, esto nos permitirá levantar nuevos servidores dentro de un cluster en cuestión de varios minutos.

 

Para ello tendremos que modificar la configuración de la BD.

En /etc/cassandra modificamos el archivo cassandra.yaml. Buscaremos la siguiente línea:

- seeds: "localhost"

Y sustituimos localhost por la ip local del servidor, en mi caso 192.168.1.10.

- seeds: "192.168.1.10"

A continuación modificamos las siguientes líneas:

listen_address: localhost

[...]

rpc_address: localhost

Por:

listen_address: 192.168.1.10

[...]

rpc_address: 192.168.1.10

Guardamos y reiniciamos el servidor.

Ahora el servidor con esta configuración será al que se conecten el resto de servidores del cluster.

Para el resto de servidores la configuración es parecida. En seeds mantenemos la ip del servidor principal y en listen_address y rpc_address ponemos la ip del servidor a unir al cluster:

- seeds: "192.168.1.10"

[...]

listen_address: 192.168.1.103

[...]

rpc_address: 192.168.1.103

Utilizo la ip 192.168.1.103 ya que es la que tengo configurada en mi cluster de prueba, tu deberías poner la ip correspondiente a la máquina donde estés configurando Cassandra.

Guardamos y reiniciamos la BD.

Esto es todo lo que hay que hacer para crear un cluster con Cassandra

Logo Cassandra

Cassandra 1.x y PHP para desarrolladores SQL: PHPCassa (I)

0

¡Por fin llego el día! ¡Hoy toca programar!

Para ello vamos a utilizar las clases de abstracción de la base de datos PHPCassa que nos ahorrará bastante tiempo para trabajar con Cassandra. Puedes descargarlo desde https://github.com/thobbs/phpcassa.

Ubicamos PHPCassa en una carpeta dentro de nuestro servidor web y creamos dos archivos. Yo los he llamado test.php y cassandra.php. El segundo será una clase que nos ahorrará algunas lineas de código con las tareas habituales. El primero lo utilizaré para testear la clase y sus respectivos métodos.

Bien empecemos.

 

PRIMEROS PASOS

En primer lugar necesitamos incluir un archivo de PHPCassa en cassandra.php:

  1. <?php
  2.  
  3. // CLASES NECESARIAS PARA CONECTAR CON CASSANDRA
  4. require_once('phpcassa/lib/autoload.php');

He inmediatamente llamamos a los namespace mínimos para trabajar con PHPCassa:

  1. <?php
  2.  
  3. use phpcassa\Connection\ConnectionPool;
  4. use phpcassa\ColumnFamily;
  5. use phpcassa\SystemManager;
  6. use phpcassa\Schema\StrategyClass;

 

Justo debajo creamos la clase:

  1. <?php
  2.  
  3. class cassandra {
  4.  
  5. }

 

CONECTANDO

Para realizar la conexión a la BD, PHPCassa nos pide tan solo un dato obligatorio: el nombre del keyspace con el que vamos a trabajar. También nos permite añadir las ips de los nodos con los que queramos trabajar, aunque por defecto su valor es localhost. Por tanto podemos crear un constructor como el siguiente:

  1. <?php
  2.  
  3. function __construct($keyspace, $nodos = array('localhost')){
  4. if (!empty($keyspace)){
  5. $this->conexion = new ConnectionPool($keyspace, $nodos);
  6. }else{
  7. print "El keyspace está vacío";
  8. }
  9. }

Este constructor nos permite indicarle a la clase el keyspace con el que queremos trabajar y la ip o nombre de servidor donde se encuentre nuestra instancia de Cassandra. Por defecto el puerto al que se va a conectar es el 9160. Si hubieses configurado Cassandra para escuchar en otro puerto deberás especificarlo: localhost:9160.

Este código nos crea una variable llamada conexion que será una instancia del objeto ConnectionPool, necesario para todas las consultas a la BD

 

GUARDANDO REGISTROS

Ahora procedemos a crear el método que guardará los registros. Para ello primero crearemos un objeto ColumnFamily al que le pasaremos el nombre de la column family en la que queremos trabajar:

  1. <?php
  2.  
  3. public function guardar($name_columnFamily, $key, $data = array()){
  4. try {
  5. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  6. $column_family->insert($key, $data);
  7. return true;
  8. }catch(Exception $e){
  9. return false;
  10. }
  11. }

Este método nos devolverá true si se ha guardado correctamente el registro, o false en caso de error.
Como puedes ver, al objeto ColumnFamily se le pasa como primer parámetro el objeto ConnectionPool que creamos en el constructor, después se le pasa el nombre de la column family.
Una vez creado el objeto ColumnFamily ya podemos utilizar el método insert para guardar el registro pasándole como parámetros la key y un array con las columnas y sus respectivos valores.

 

RECUPERANDO REGISTROS

Recuperar registros de Cassandra es algo más complejo que guardarlos:

Primero debemos añadir un nuevo namespace que nos permitirá usar una clase que nos será muy útil. El listado de namespaces nos quedaría así:

  1. <?php
  2.  
  3. use phpcassa\Connection\ConnectionPool;
  4. use phpcassa\ColumnFamily;
  5. use phpcassa\ColumnSlice;
  6. use phpcassa\SystemManager;
  7. use phpcassa\Schema\StrategyClass;

A continuación creamos el método en nuestro archivo cassandra.php:

 

  1. <?php
  2.  
  3. public function obtener($name_columnFamily, $key, $column_names= NULL, $range_start = "", $range_end = "", $column_count = 100, $invertir_orden=false){
  4.  
  5. try{
  6. $column_slices = new ColumnSlice($range_start, $range_end, $column_count, $invertir_orden);
  7. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  8. $result = $column_family->get($key, $column_slices, $column_names);
  9. }catch(Exception $e){
  10. return false;
  11. }
  12.  
  13. return $result;
  14.  
  15. }

 

Este método tiene algunos parámetros más que al guardar, pero tienen su razón de ser:

$columnFamily: Nombre de la column family donde buscar.
$key: Clave del registro donde buscar.
$columns: Columnas a buscar. No es obligatorio. Por defecto NULL.
$range_start: Key por la que Cassandra debe empezar a recuperar registros. No es obligatorio. Por defecto “”.$range_end: Key por la que Cassandra dejará de recuperar registros. No es obligatorio. Por defecto “”.
$column_count: Número de registros a obtener, Por defecto 100.
$invertir_orden: Invierte el orden en el que se recuperar los registros. De mayor a menor o viceversa, de la A-Z o viceversa, etc.

Como ves tienes bastantes opciones para recuperar registros. Este método devuelve un array con los registros.

 

PROBANDO LA CLASE

Vamos a probar el código a ver que tal funciona. Nos vamos al archivo test.php y escribimos el siguiente código:

  1. <?php
  2.  
  3. include_once "cassandra.php";
  4.  
  5. $cass = new cassandra('my_keyspace', array('192.168.1.10'));
  6.  
  7. $data = array(
  8. 'nombre' => 'pepito',
  9. 'ciudad' => 'Madrid',
  10. 'vehiculo' => 'coche',
  11. );
  12.  
  13. if ( $cass->guardar('my_column_family_standard', $key=1, $data)){
  14. print "El registro se ha guardado correctamente<br />";
  15. }else{
  16. print "Error al guardar el registro<br />";
  17. }
  18.  
  19. $result = $cass->obtener('my_column_family_standard', $key=1);
  20.  
  21. print_r($result);
  22. ?>

Explico un poco el código anterior:

  1. Incluimos la clase en el archivo.
  2. Creamos el objeto indicándole el keyspace con el que trabajar (my_keyspace), y dentro de un array, la ip donde se encuentra en nodo de Cassandra. Si tuvieses Cassandra instalado en localhost no sería necesario indicar el segundo parámetro.
  3. Creamos el array que contendrá los datos a guardar.
  4. Creamos un condicional que guardará los datos en Cassandra y nos indicará si se han guardado correctamente o ha habido algún error.
  5. Guardamos en una variable ($result) los registros que recuperamos a través del método obtener del objeto $cass. A este método le indicamos la column family a buscar y la key a obtener.
  6. Mostramos los registros.

Si todo ha salido correctamente verás un texto como el siguiente cuando ejecutes el script:

El registro se ha guardado correctamente
 Array ( [ciudad] => Madrid [nombre] => pepito [vehiculo] => coche )

Si te aparecen más registros es posible que no vaciases las column family con la que trabajas. Simplemente ves a Cassandra Cluster Admin, entra en la column family y pulsa en Truncate Column Family. Así eliminarás todos los datos de la column family.

 

ACTUALIZAR UN REGISTRO

Ahora que ya funciona nuestra clase podemos ampliarla con nuevas características.
Aunque pienses que para actualizar un registro es necesario un nuevo método, en Cassandra no es necesario, simplemente utilizaremos el método guardar indicandole la key a modificar y el array con los datos a guardar.

Justo debajo del código que ya tenemos en el archivo test.php escribimos lo siguiente:

  1. <?php
  2.  
  3. $data = array(
  4. 'ciudad' => 'Barcelona',
  5. );
  6.  
  7. if ( $cass->guardar('my_column_family_standard', $key=1, $data)){
  8. print "El registro se ha guardado correctamente<br />";
  9. }else{
  10. print "Error al guardar el registro<br />";
  11. }
  12.  
  13. $result = $cass->obtener('my_column_family_standard', $key=1);
  14.  
  15. print_r($result);

Como observarás el array no tiene todos los datos de la key que vamos a modificar, ya que no es necesario, tan solo pasaremos los datos que queremos actualizar. El resultado de este código es el siguiente:

El registro se ha guardado correctamente
 Array ( [ciudad] => Madrid [nombre] => pepito [vehiculo] => coche )
 El registro se ha guardado correctamente
 Array ( [ciudad] => Barcelona [nombre] => pepito [vehiculo] => coche )

La columna ciudad a cambiado, el resto sigue igual, la razón está en que cuando le pasas a Cassandra una key que ya existe, lo que hace es actualizar las columnas que se correspondan con las keys del array. Si en ese array hubiera keys que no existen como columnas en el registro, Cassandra simplemente las crearía nuevas.

 

GUARDANDO UNA SUPER COLUMN

Aquí tampoco nos hace falta crear un nuevo método ya que nos sirve perfectamente el método guardar, pero deberemos hacerle algunas modificaciones.

En primer lugar, para trabajar con column families super es necesario añadir una llamada al namespace concreto. La lista de namespaces quedaría de la siguiente manera:

  1. <?php
  2.  
  3. use phpcassa\Connection\ConnectionPool;
  4. use phpcassa\ColumnFamily;
  5. use phpcassa\SuperColumnFamily;
  6. use phpcassa\ColumnSlice;
  7. use phpcassa\SystemManager;
  8. use phpcassa\Schema\StrategyClass;

Ahora debemos modificar el método guardar y añadirle el parámetro $is_super_column, que nos permitirá crear un objeto SuperColumnFamily o ColumnFamily según corresponda. El método nos quedaría así:

  1. <?php
  2.  
  3. public function guardar($name_columnFamily, $key, $data = array(), $is_super_column = false){
  4.  
  5. try {
  6. if ($is_super_column){
  7. $column_family = new SuperColumnFamily($this->conexion, $name_columnFamily);
  8. }
  9. else{
  10. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  11. }
  12.  
  13. $column_family->insert($key, $data);
  14. return true;
  15. }catch(Exception $e){
  16. return false;
  17. }
  18. }

Como ambas clases comparten el método insert no nos hace falta incluir esa linea dentro del condicional.

A continuación modificamos el método obtener con el mismo parámetro y utilizando el mismo sistema para crear el objeto correspondiente:

  1. <?php
  2.  
  3. public function obtener($name_columnFamily, $key, $is_super_column=false, $column_names= NULL, $range_start = "", $range_end = "", $column_count = 100, $invertir_orden=false){
  4.  
  5. try{
  6. if ($is_super_column){
  7. $column_family = new SuperColumnFamily($this->conexion, $name_columnFamily);
  8. }
  9. else{
  10. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  11. }
  12. $column_slices = new ColumnSlice($range_start, $range_end, $column_count, $invertir_orden);
  13. $result = $column_family->get($key, $column_slices, $column_names);
  14. }catch(Exception $e){
  15. return false;
  16. }
  17.  
  18. return $result;
  19.  
  20. }

Ahora podemos añadir el siguiente código a nuestro archivo test.php:

  1. <?php
  2.  
  3. $data = array('vecino_1' => array(
  4. 'nombre' => 'pepito',
  5. 'ciudad' => 'Madrid',
  6. 'vehiculo' => 'coche',
  7. ));
  8.  
  9. if ( $cass->guardar('my_column_family_super', $key=1, $data, $is_super_column=true)){
  10. print "El registro se ha guardado correctamente<br />";
  11. }else{
  12. print "Error al guardar el registro<br />";
  13. }
  14.  
  15. $result = $cass->obtener('my_column_family_super', $key=1, $is_super_column=true);
  16.  
  17. print_r($result);

El único cambio además del nombre de la column family donde vamos a guardar el registro, se encuentra en el array con los datos. Este tiene un elemento que es la key de la super column, y como valor, el array de las columns a guardar.

Si ejecutamos el código anterior nos devolverá lo siguiente:

El registro se ha guardado correctamente
 Array ( [vecino_1] => Array ( [ciudad] => Madrid [nombre] => pepito [vehiculo] => coche ) )

[ci-box type=”warning”]Al probar el código, PHP me devolvió el siguiente aviso:
Strict Standards: Declaration of phpcassa\SuperColumnFamily::add() should be compatible with that of phpcassa\ColumnFamily::add() in /var/www/prueba_cassandra/phpcassa/lib/phpcassa/SuperColumnFamily.php on line 491. 

No te preocupes no afecta ni a los ejemplos ni a la clase que funcionan correctamente.[/ci-box]

ACTUALIZANDO UNA SUPER COLUMN

La actualización de una super column se limita a las columnas que contienen los valores del registro no a su key. Si modificáramos la key , lo que en realidad estaríamos haciendo sería crear una nueva super column. Añadimos el siguiente código a nuestro archivo test.php:

  1. <?php
  2.  
  3. $data = array('vecino_1' => array(
  4. 'nombre' => 'pepito',
  5. 'ciudad' => 'Barcelona',
  6. 'vehiculo' => 'coche',
  7. ));
  8.  
  9. if ( $cass->guardar('my_column_family_super', $key1, $data, $is_super_column=true)){
  10. print "El registro se ha guardado correctamente<br />";
  11. }else{
  12. print "Error al guardar el registro<br />";
  13. }
  14.  
  15. $result = $cass->obtener('my_column_family_super', $key=1, $is_super_column=true);
  16.  
  17. print_r($result);

Y el resultado es:

El registro se ha guardado correctamente
 Array ( [vecino_1] => Array ( [ciudad] => Barcelona [nombre] => pepito [vehiculo] => coche ) )

 

ELIMINAR REGISTROS

Sí, aquí toca crear un nuevo método para nuestra clase en cassandra.php, aunque tampoco nos vamos a matar programando:

 

  1. <?php
  2.  
  3. public function eliminar($name_columnFamily, $key, $is_super_column = false){
  4.  
  5. try{
  6. if ($is_super_column){
  7. $column_family = new SuperColumnFamily($this->conexion, $name_columnFamily);
  8. }
  9. else{
  10. $column_family = new ColumnFamily($this->conexion, $name_columnFamily);
  11. }
  12. $column_family->remove($key);
  13. return true;
  14. }catch(Exception $e){
  15. return false;
  16. }
  17. }

 

El método es bastante sencillo: se le pasan tres parámetros que ya conocemos.

Dentro del método se crea un objeto ColumnFamily y se utiliza el método remove para eliminar el registro pasándole la key correspondiente, y si fuese una super column, la key de este.
El método remove tiene un segundo parámetro que por defecto tiene un valor null, en él se pueden añadir como array los nombres de las columnas a eliminar. Como no es habitual ese proceso he creído adecuado no utilizarlo.

Una vez añadido esté método a nuestra clase modificamos el archivo test.php con el siguiente código:

  1. <?php
  2.  
  3. if ( $cass->eliminar('my_column_family_standard', $key=1)){
  4. print "El registro se ha eliminado correctamente<br />";
  5. }else{
  6. print "Error al eliminar el registro<br />";
  7. }
  8.  
  9. $result = $cass->obtener('my_column_family_standard', $key=1);
  10.  
  11. print_r($result);

Y el resultado es:

El registro se ha eliminado correctamente

 

De momento con esto es suficiente, dejo en tus manos estos métodos para que juegues con ellos todo lo que quieras y te familiarices con PHPCassa.

En el próximo post trataré las Counter Columns que nos servirán para contar registros, los Secondary Index que nos permitirán realizar búsquedas por columnas concretas, y algunas cosas más.

Logo Cassandra

Cassandra 1.x y PHP para desarrolladores SQL: Instalación

4

La base de datos No-SQL Cassandra fue creada por Facebook a causa de la necesidad de disponer de una base de datos distribuida de alto rendimiento, flexible, tolerante a fallos, escalable y que fuese capaz de procesar grandes cantidades de datos, más tarde fue liberada bajo licencia Apache y actualmente es utilizada principalmente por empresas de internet con proyectos con un alto uso de base de datos como Twitter.

En esta serie de artículos iré desgranando la instalación, funcionamiento y desarrollo de aplicaciones en PHP con Cassandra, comparando las sentencias utilizadas para insertar, actualizar, etc de SQL con los métodos a utilizar en Cassandra. Por desgracia al ser algo completamente distinto a cualquier base de datos SQL tendré que añadir algo de teoría, pero intentaré que os resulte lo más ameno posible.

Al toro.

REQUISITOS

Para la realización de esta guía se utilizará Debian Squeeze como sistema operativo.

Doy por hecho que ya se dispone de un servidor web Apache con PHP instalado en la máquina de testeo que se esté usando. Las aplicaciones que se van a instalar han sido probadas en una máquina virtual Debian utilizando como aplicación de virtualización, VirtualBox instalado en un host Windows XP SP3.

En un servidor de producción recomiendo que tenga bastante RAM (por encima de 1GB, ya veremos más adelante el porqué. En la máquina virtual que uso de testeo dispone de 700 MB y funciona bien, pero en producción no es lo recomendable).

Instalaremos la base de datos Cassandra, el protocolo para conectar con ella y que nos generará el módulo para poder trabajar desde PHP, y PHPCassa que será la abstracción de la base de datos donde tenemos los métodos básicos para trabajar con Cassandra: insertar, actualizar, borrar, crear, etc.

PREPARANDO EL SISTEMA

Antes de empezar a instalar debemos actualizar el sistema operativos de la forma habitual:

apt-get update
apt-get upgrade

Una vez actualizado el sistema empezamos a instalar.

INSTALANDO CASSANDRA

Lo primero que necesitamos hacer para instalar Cassandra es editar los repositorios de Debian:

nano /etc/apt/sources.list

Una vez que se abra el editor añadimos las siguientes lineas:

deb http://www.apache.org/dist/cassandra/debian/ 11x main
deb-src http://www.apache.org/dist/cassandra/debian/ 11x main

Como podrás observar después de la ruta del repositorio se ha añadido “11x” esto indica el número de versión a obtener, en este caso es la versión actual de cassandra al crear este post. No se indica el número de parche, es decir, actualmente se puede descargar Cassandra 1.1.

Si dentro de unos meses sale la versión “1.2” solo tendrás que cambiar el uno por el dos.
Volvemos a consola y actualizamos los repositorios.

apt-get update

Nos dará un error en las claves gpg. Procedemos a actualizarlas con las siguientes instrucciones:

gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D
gpg --export --armor F758CE318D77295D | sudo apt-key add -

Ojo con el guión del final, hay que añadirlo sino dará error.

Con el paquete 0.7.5 nos da otro error de clave gpg así que también instalamos esta de la misma manera:

gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00
gpg --export --armor 2B5C1B00 | sudo apt-key add -

Verificamos que tenemos el sistema actualizado.

apt-get update
apt-get upgrade

Actualizamos todos los paquetes que aparezcan.

Procedemos a instalar el paquete de la base de datos NoSQL Cassandra:

apt-get install cassandra

Cassandra necesita a Java para funcionar para ello, una vez instalado Cassandra instalaremos el paquete sun-java6-jdk de la siguiente manera:

apt-get install sun-java6-jdk

En el caso de que no encuentre el paquete verificar que los repositorios de Debian son correctos. Verifica la versión de Java con:

java -version

Debería aparecer algo así:

java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)

Se recomienda usar la versión de Java de Sun (Sun JDK) en vez de Open JDK debido a un bug encontrado en el mismo.

Si os muestra algo distinto a esto, escribid el siguiente comando:

update-alternatives --config javac

Os mostrará un listado con los diferentes paquetes instalados en el sistema que pueden ser utilizados para trabajar con Java. Nosotros usaremos el paquete de Sun, así que pulsa el número del paquete para que Debian lo utilice.

Por último, ejecutamos el siguiente comando para construir las dependencias:

dpkg-buildpackage -uc -us

INSTALANDO THRIFT Y LA EXTENSIÓN PARA PHP

[ci-box type=”info”]PHPCassa ya incluye Thrift en el archivo descargable, con lo que puedes saltarte esta parte si quieres. En la sección de PHPCassa se trata la creación del archivo .so con los archivos contenidos en el paquete de PHPCassa[/ci-box]

Thrift es tan solo el protocolo de conexión para poder utilizar Cassandra. Aunque en la extensión para PHP existen métodos para poder trabajar con cassandra, requieren bastante código por eso utilizaremos PHPCassa como abstracción de la base de datos.

Primero descargamos Thrift desde su web: http://thrift.apache.org/download/ y descomprimimos

tar -xzvf thrift-0.8.0.tar.gz

Nos colocamos dentro de la carpeta de Thrift.

Antes de hacer nada ahí instalamos algunos paquetes que nos serán necesarios:

apt-get install libboost-dev automake libtool flex bison pkg-config g++

Una vez instalados esos paquetes configuramos y construimos Thrift:

./configure
make

Construimos la interfaz de PHP Thrift para Cassandra:

./compiler/cpp/thrift -gen php ../ruta-a-cassandra/interface/cassandra.thrift

Copiamos archivos necesario para que PHPCassa funcione:

mkdir -p /usr/share/php/Thrift
cp -R gen-php/ /usr/share/php/Thrift/packages/
cp -R lib/php/src/* /usr/share/php/Thrift/

Cambiamos al directorio del protocolo de Thrif: ruta-a-thrift/lib/php/src/ext/thrift_protocol.

Instalamos el paquete para construir las extensiones de PHP:

apt-get install php5-dev

Construimos la extensión:

phpize
./configure --enable-thrift_protocol
make

Copiamos la extensión a la siguiente carpeta (cuidado: dependiendo del sistema el nombre de la carpeta de destino puede variar):

cp modules/thrift_protocol.so /usr/lib/php5/20060613/

Habilitamos el módulo creando el archivo /etc/php5/conf.d/thrift_protocol.ini con el siguiente texto:

extension=thrift_protocol.so

Comprobamos la instalación:

php -i | grep -v "PWD" | grep "thrift_protocol"

Si todo ha ido bien, reiniciamos Apache:

/etc/init.d/apache2 restart

Iniciamos Cassandra:

/opt/cassandra/bin/cassandra

Y probamos la consola para comprobar que todo ha ido correctamente:

/opt/cassandra/bin/cassandra-cli -host localhost -port 9160

Debería indicarte algo así:

Connected to: "Test Cluster" on localhost/9160
Welcome to cassandra CLI.

INSTALANDO PHPCassa

Bajamos PHPCassa desde github: https://github.com/thobbs/phpcassa

Descomprimimos a una carpeta dentro del proyecto en el que vayamos a utilizar PHPCassa, para el tutorial usaré /var/www/prueba_cassandra/phpcassa.

Si aun no has creado el archivo .so para que PHP pueda trabajar con Cassandra, escribe los siguientes comandos en tu consola:

cd lib/thrift/ext/thrift_protocol 
phpize 
./configure 
make 
sudo make install

Una vez finalizados estos pasos edita el archivo php.ini y añade la siguiente línea:

extension=thrift_protocol.so

Con esto finalizamos la instalación de Cassandra para que pueda ser utilizada por PHP.

 

Logo Cassandra

Cassandra y PHP para desarrolladores SQL: Clusters

0

Cassandra permite crear anillos o clusters de servidores de una forma muy sencilla, esto nos permitirá levantar nuevos servidores dentro de un cluster en cuestión de varios minutos.

 

Para ello tendremos que modificar la configuración de la BD.

En /etc/cassandra modificamos el archivo cassandra.yaml. Buscaremos la siguiente línea:

– seeds: “localhost”

Y sustituimos localhost por la ip local del servidor, en mi caso 192.168.1.10.

– seeds: “192.168.1.10”

A continuación modificamos las siguientes líneas:

listen_address: localhost

[…]

rpc_address: localhost

Por:

listen_address: 192.168.1.10

[…]

rpc_address: 192.168.1.10

Guardamos y reiniciamos el servidor.

Ahora el servidor con esta configuración será al que se conecten el resto de servidores del cluster.

Para el resto de servidores la configuración es parecida. En seeds mantenemos la ip del servidor principal y en listen_address y rpc_address ponemos la ip del servidor a unir al cluster:

– seeds: “192.168.1.10”

[…]

listen_address: 192.168.1.103

[…]

rpc_address: 192.168.1.103

Utilizo la ip 192.168.1.103 ya que es la que tengo configurada en mi cluster de prueba, tu deberías poner la ip correspondiente a la máquina donde estés configurando Cassandra.

Guardamos y reiniciamos la BD.

Esto es todo lo que hay que hacer para crear un cluster con Cassandra

Logo Cassandra

Cassandra y PHP para desarrolladores SQL: PHPCassa (I)

10

¡Por fin llego el día! ¡Hoy toca programar!

Para ello vamos a utilizar el cliente de alto nivel PHPCassa que nos ahorrará bastante tiempo para trabajar con Cassandra. Puedes descargarlo desde https://github.com/thobbs/phpcassa.

Ubicamos phpCassa en una carpeta dentro de nuestro servidor web y creamos dos archivos. Yo los he llamado test.php y cassandra.php, El segundo será una clase que nos ahorrará algunas lineas de código con las tareas habituales. El primero lo utilizaré para testear la clase y sus respectivos métodos.

Bien empecemos.

 

PRIMEROS PASOS

En primer lugar necesitamos incluir dos archivos de phpCassa en cassandra.php:

  1. <?php
  2.  
  3. // CLASES NECESARIAS PARA CONECTAR CON CASSANDRA
  4. require_once('phpcassa/connection.php');
  5. require_once('phpcassa/columnfamily.php');

El primero de ellos dispone de los métodos para conectar con Cassandra a través de Thirft; el segundo tiene los métodos para trabajar con las column families.

Justo debajo creamos la clase:

  1. <?php
  2.  
  3. class cassandra {
  4.  
  5. }

 

CONECTANDO

Para realizar la conexión a la BD, phpCassa nos pide tan solo un dato obligatorio: el nombre del keyspace con el que vamos a trabajar. También nos permite añadir las ips de los nodos con los que queramos trabajar, aunque por defecto su valor es localhost. Por tanto podemos crear un constructor como el siguiente:

  1. <?php
  2.  
  3. function __construct($keyspace, $nodos = array('localhost')){
  4. if (!empty($keyspace)){
  5. $this->conexion = new ConnectionPool($keyspace, $nodos);
  6. }else{
  7. print "El keyspace está vacío";
  8. }
  9. }

Este constructor nos permite indicarle a la clase el keyspace con el que queremos trabajar y la ip o nombre de servidor donde se encuentre nuestra instancia de Cassandra. Por defecto el puerto al que se va a conectar es el 9160. Si hubieses configurado Cassandra para escuchar en otro puerto deberás especificarlo: localhost:9160.

Este código nos crea una variable llamada conexion que contendrá el objeto ConnectionPool, necesario para todas las consultas a la BD

 

GUARDANDO REGISTROS

Ahora procedemos a crear el método que guardará los registros. Para ello primero crearemos un objeto ColumnFamily al que le pasaremos el nombre de la column family en la que queremos trabajar:

  1. <?php
  2.  
  3. public function guardar($columnFamily, $key, $data = array()){
  4. try {
  5. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  6. $column_family->insert($key, $data);
  7. return true;
  8. }catch(Exception $e){
  9. return false;
  10. }
  11. }

Este método nos devolverá true si se ha guardado correctamente el registro, o false en caso de error.
Como puedes ver, al objeto ColumnFamily se le pasa como primer parámetro el objeto ConnectionPool que creamos en el constructor, después se le pasa el nombre de la column family.
Una vez creado el objeto ColumnFamily ya podemos utilizar el método insert para guardar el registro pasándole como parámetros la key y un array con las columnas y sus respectivos valores.

 

RECUPERANDO REGISTROS

Recuperar registros de Cassandra es algo más complejo que guardarlos:

  1. <?php
  2.  
  3. public function obtener($columnFamily, $key, $super_column=NULL, $columns= NULL, $range_start = "", $column_count = 100, $invertir_orden=false){
  4.  
  5. try{
  6. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  7. $result = $column_family->get($key, $columns, $range_start, "", $invertir_orden, $column_count, $super_column);
  8. }catch(Exception $e){
  9. return false;
  10. }
  11.  
  12. return $result;
  13.  
  14. }

Este método tiene algunos parámetros más que al guardar, pero tienen su razón de ser:

$columnFamily: Nombre de la column family donde buscar.
$key: Clave del registro donde buscar.
$super_column: Key o clave de la super column que se debe buscar. No es obligatorio. Por defecto NULL.
$columns: Columnas a buscar. No es obligatorio. Por defecto NULL.
$range_start: Key por la que Cassandra debe empezar a recuperar registros. No es obligatorio. Por defecto “”.
$column_count: Número de registros a obtener, Por defecto 100.
$invertir_orden: Invierte el orden en el que se recuperar los registros. De mayor a menor o viceversa, de la A-Z o viceversa, etc.

Como ves tienes bastantes opciones para recuperar registros. Este método devuelve un array con los registros.

 

PROBANDO LA CLASE

Vamos a probar el código a ver que tal funciona. Nos vamos al archivo test.php y escribimos el siguiente código:

  1. <?php
  2.  
  3. include_once "cassandra.php";
  4.  
  5. $cass = new cassandra('my_keyspace', array('192.168.1.10'));
  6.  
  7. $data = array(
  8. 'nombre' => 'pepito',
  9. 'ciudad' => 'Madrid',
  10. 'vehiculo' => 'coche',
  11. );
  12.  
  13. if ( $cass->guardar('my_column_family_standard', 1, $data)){
  14. print "El registro se ha guardado correctamente<br />";
  15. }else{
  16. print "Error al guardar el registro<br />";
  17. }
  18.  
  19. $result = $cass->obtener('my_column_family_standard', 1);
  20.  
  21. print_r($result);
  22. ?>

Explico un poco el código anterior:

  1. Incluimos la clase en el archivo.
  2. Creamos el objeto indicándole el keyspace con el que trabajar (my_keyspace), y dentro de un array, la ip donde se encuentra en nodo de Cassandra. Si tuvieses Cassandra instalado en localhost no sería necesario indicar el segundo parámetro.
  3. Creamos el array que contendrá los datos a guardar.
  4. Creamos un condicional que guardará los datos en Cassandra y nos indicará si se han guardado correctamente o ha habido algún error.
  5. Guardamos en una variable ($result) los registros que recuperamos a través del método obtener del objeto $cass. A este método le indicamos la column family a buscar y la key a obtener.
  6. Mostramos los registros.

Si todo ha salido correctamente verás un texto como el siguiente cuando ejecutes el script:

El registro se ha guardado correctamente
Array ( [ciudad] => Madrid [nombre] => pepito [vehiculo] => coche )

Si te aparecen más registros es posible que no vaciases las column family con la que trabajas. Simplemente ves a cassAdmin, entra en la column family y pulsa en Truncate Column Family. Así eliminarás todos los datos de la column family.

 

ACTUALIZAR UN REGISTRO

Ahora que ya funciona nuestra clase podemos ampliarla con nuevas características.
Aunque pienses que para actualizar un registro es necesario un nuevo método, en Cassandra no es necesario, simplemente utilizaremos el método guardar indicandole la key a modificar y el array con los datos a guardar.

Justo debajo del código que ya tenemos en el archivo test.php escribimos lo siguiente:

  1. <?php
  2.  
  3. $data = array(
  4. 'ciudad' => 'Barcelona',
  5. );
  6.  
  7. if ( $cass->guardar('my_column_family_standard', 1, $data)){
  8. print "El registro se ha guardado correctamente<br />";
  9. }else{
  10. print "Error al guardar el registro<br />";
  11. }
  12.  
  13. $result = $cass->obtener('my_column_family_standard', 1);
  14.  
  15. print_r($result);

Como observarás el array no tiene todos los datos de la key que vamos a modificar, ya que no es necesario, tan solo pasaremos los datos que queremos actualizar. El resultado de este código es el siguiente:

El registro se ha guardado correctamente
Array ( [ciudad] => Madrid [nombre] => pepito [vehiculo] => coche )
El registro se ha guardado correctamente
Array ( [ciudad] => Barcelona [nombre] => pepito [vehiculo] => coche )

La columna ciudad a cambiado, el resto sigue igual, la razón está en que cuando le pasas a Cassandra una key que ya existe, lo que hace es actualizar las columnas que se correspondan con las keys del array. Si en ese array hubiera keys que no existen como columnas en el registro, Cassandra simplemente las crearía nuevas.

 

GUARDANDO UNA SUPER COLUMN

Aquí tampoco nos hace falta crear un nuevo método ya que nos sirve perfectamente el método guardar.

Añadimos el siguiente código a nuestro archivo test.php:

  1. <?php
  2.  
  3. $data = array('vecino_1' => array(
  4. 'nombre' => 'pepito',
  5. 'ciudad' => 'Madrid',
  6. 'vehiculo' => 'coche',
  7. ));
  8.  
  9. if ( $cass->guardar('my_column_family_super', 1, $data)){
  10. print "El registro se ha guardado correctamente<br />";
  11. }else{
  12. print "Error al guardar el registro<br />";
  13. }
  14.  
  15. $result = $cass->obtener('my_column_family_super', 1);
  16.  
  17. print_r($result);

El único cambio además del nombre de la column family donde vamos a guardar el registro, se encuentra en el array con los datos. Este tiene un elemento que es la key de la super column, y como valor, el array de las columns a guardar.

Si ejecutamos el código anterior nos devolverá lo siguiente:

El registro se ha guardado correctamente
Array ( [vecino_1] => Array ( [ciudad] => Madrid [nombre] => pepito [vehiculo] => coche ) )

 

ACTUALIZANDO UN SUPER COLUMN

La actualización de una super column se limita a las columnas que contienen los valores del registro no a su key. Si modificáramos la key , lo que en realidad estaríamos haciendo sería crear una nueva super column. Añadimos el siguiente código a nuestro archivo test.php:

  1. <?php
  2.  
  3. $data = array('vecino_1' => array(
  4. 'nombre' => 'pepito',
  5. 'ciudad' => 'Barcelona',
  6. 'vehiculo' => 'coche',
  7. ));
  8.  
  9. if ( $cass->guardar('my_column_family_super', 1, $data)){
  10. print "El registro se ha guardado correctamente<br />";
  11. }else{
  12. print "Error al guardar el registro<br />";
  13. }
  14.  
  15. $result = $cass->obtener('my_column_family_super', 1);
  16.  
  17. print_r($result);

Y el resultado es:

El registro se ha guardado correctamente
Array ( [vecino_1] => Array ( [ciudad] => Barcelona [nombre] => pepito [vehiculo] => coche ) )

 

ELIMINAR REGISTROS

Sí, aquí toca crear un nuevo método para nuestra clase en cassandra.php, aunque tampoco nos vamos a matar programando:

  1. <?php
  2.  
  3. public function eliminar($columnFamily, $key, $super_column = null){
  4.  
  5. try{
  6. $column_family = new ColumnFamily($this->conexion, $columnFamily);
  7. $column_family->remove($key, null, $super_column);
  8. return true;
  9. }catch(Exception $e){
  10. return false;
  11. }
  12. }

El método es bastante sencillo: se le pasan tres parámetros que ya conocemos.

Dentro del método se crea un objeto ColumnFamily y se utiliza el método remove para eliminar el registro pasándole la key correspondiente, y si fuese una super column, la key de este.
Observarás que el segundo parámetro del método remove tiene un valor null, en él se pueden añadir como array los nombres de las columnas a eliminar. Como no es habitual ese proceso he creído adecuado dejarlo como null.

Una vez añadido esté método a nuestra clase modificamos el archivo test.php con el siguiente código:

  1. <?php
  2.  
  3. if ( $cass->eliminar('my_column_family_standard', 1)){
  4. print "El registro se ha eliminado correctamente<br />";
  5. }else{
  6. print "Error al eliminar el registro<br />";
  7. }
  8.  
  9. $result = $cass->obtener('my_column_family_standard', 1);
  10.  
  11. print_r($result);

Y el resultado es:

El registro se ha eliminado correctamente

 

De momento con esto es suficiente, dejo en tus manos estos métodos para que juegues con ellos todo lo que quieras y te familiarices con phpCassa.

En el próximo post trataré las Counter Columns que nos servirán para contar registros, los Secondary Index que nos permitirán realizar búsquedas por columnas concretas, y algunas cosas más.

Cassandra y PHP para desarrolladores SQL: Instalación

6

La base de datos No-SQL Cassandra fue creada por Facebook a causa de la necesidad de disponer de una base de datos distribuida de alto rendimiento, flexible, tolerante a fallos, escalable y que fuese capaz de procesar grandes cantidades de datos, más tarde fue liberada bajo licencia Apache y actualmente es utilizada principalmente por empresas de internet con proyectos con un alto uso de base de datos como Twitter.

En esta serie de artículos iré desgranando la instalación, funcionamiento y desarrollo de aplicaciones en PHP con Cassandra, comparando las sentencias utilizadas para insertar, actualizar, etc de SQL con los métodos a utilizar en Cassandra. Por desgracia al ser algo completamente distinto a cualquier base de datos SQL tendré que añadir algo de teoría, pero intentaré que os resulte lo más ameno posible.

Al toro.

 

 

REQUISITOS

Para la realización de esta guía se utilizará Debian Squeeze como sistema operativo. En algunos de los links que dejo como bibliografía al final del artículo existen ejemplos para realizar la instalación en otros sistemas operativos, principalmente CentOS.

Doy por hecho que ya se dispone de un servidor web Apache con PHP instalado en la máquina de testeo que se esté usando. Las aplicaciones que se van a instalar han sido probadas en una máquina virtual Debian utilizando como aplicación de virtualización, VirtualBox instalado en un host Windows XP SP3.

En un servidor de producción recomiendo que tenga bastante RAM (por encima de 1GB, ya veremos más adelante el porqué. En la máquina virtual que uso de testeo dispone de 700 MB y funciona bien, pero en producción no es lo recomendable).

Instalaremos la base de datos Cassandra, el protocolo para conectar con ella y que nos generará el módulo para poder trabajar desde PHP, y PHPCassa que será la abstracción de la base de datos donde tenemos los métodos básicos para trabajar con Cassandra: insertar, actualizar, borrar, crear, etc.

 

PREPARANDO EL SISTEMA

Antes de empezar a instalar debemos actualizar el sistema operativos de la forma habitual:

apt-get update
apt-get upgrade

Una vez actualizado el sistema empezamos a instalar.

 

INSTALANDO CASSANDRA

Lo primero que necesitamos hacer para instalar Cassandra es editar los repositorios de Debian:

  1. nano /etc/apt/sources.list

 

Una vez que se abra el editor añadimos las siguientes lineas:

deb http://www.apache.org/dist/cassandra/debian/ 08x main
deb-src http://www.apache.org/dist/cassandra/debian/ 08x main

Como podrás observar después de la ruta del repositorio se ha añadido “08x” estoy indica el número de versión a obtener, en este caso es la versión actual de cassandra al crear este post. No se indica el número de parche, es decir, actualmente se puede descargar Cassandra 8.4, el “.4” lo obviamos a la hora de los repositorios.

Si dentro de unos meses sale la versión “9.0” solo tendrás que cambiar el ocho por el nueve.
Volvemos a consola y actualizamos los repositorios.

apt-get update

Nos dará un error en las claves gpg. Procedemos a actualizarlas con las siguientes instrucciones:

  1. gpg --keyserver pgp.mit.edu --recv-keys F758CE318D77295D
  2. gpg --export --armor F758CE318D77295D | sudo apt-key add -

Ojo con el guión del final, hay que añadirlo sino dará error.

Con el paquete 0.7.5 nos da otro error de clave gpg así que también instalamos esta de la misma manera:

gpg --keyserver pgp.mit.edu --recv-keys 2B5C1B00
gpg --export --armor 2B5C1B00 | sudo apt-key add -

Verificamos que tenemos el sistema actualizado.

Actualizamos todos los paquetes que aparezcan.

Procedemos a instalar el paquete de la base de datos NoSQL Cassandra:

  1. apt-get install cassandra

Cassandra necesita a Java para funcionar para ello, una vez instalado Cassandra instalaremos el paquete sun-java6-jdk de la siguiente manera:

  1. apt-get install sun-java6-jdk

En el caso de que no encuentre el paquete verificar que los repositorios de Debian son correctos. Verifica la versión de Java con:

Debería aparecer algo así:

java version "1.6.0_20"
Java(TM) SE Runtime Environment (build 1.6.0_20-b02)
Java HotSpot(TM) Client VM (build 16.3-b01, mixed mode, sharing)

Se recomienda usar la versión de Java de Sun (Sun JDK) en vez de Open JDK debido a un bug encontrado en el mismo.

Si os muestra algo distinto a esto, escribid el siguiente comando:

update-alternatives --config javac

Os mostrará un listado con los diferentes paquetes instalados en el sistema que pueden ser utilizados para trabajar con Java. Nosotros usaremos el paquete de Sun, así que pulsa el número del paquete para que Debian lo utilice.

Por último, ejecutamos el siguiente comando para construir las dependencias:

dpkg-buildpackage -uc -us

Una vez instalado procedemos a realizar la configuración de Cassandra:

Creamos varias carpetas necesarias si no han sido creadas automáticamente:

  1. mkdir -p {callouts,commitlog,data,saved,caches,staging}
  2. mkdir /var/log/cassandra

Damos permisos a esta carpeta:

chmod -R 777 /var/log/cassandra/

Creamos el archivo /var/log/cassandra/system.log y le damos permisos:

chmod -R 777 /var/log/cassandra/system.log

 

INSTALANDO THRIFT Y LA EXTENSIÓN PARA PHP

Thrift es tan solo el protocolo de conexión para poder utilizar Cassandra. Aunque en la extensión para PHP existen métodos para poder trabajar con cassandra, requieren bastante código por eso utilizaremos PHPCassa como abstracción de la base de datos.

Primero descargamos Thrift desde su web: http://thrift.apache.org/download/ y descomprimimos

  1. tar -xzvf thrift-0.7.0.tar.gz

Nos colocamos dentro de la carpeta de Thrift.

Antes de hacer nada ahí instalamos algunos paquetes que nos serán necesarios:

  1. apt-get install libboost-dev automake libtool flex bison pkg-config g++

Una vez instalados esos paquetes configuramos y construimos Thrift:

  1. ./configure
  2. make

Construimos la interfaz de PHP Thrift para Cassandra:

  1. ./compiler/cpp/thrift -gen php ../ruta-a-cassandra/interface/cassandra.thrift

Copiamos archivos necesario para que PHPCassa funcione:

  1. mkdir -p /usr/share/php/Thrift
  2. cp -R gen-php/ /usr/share/php/Thrift/packages/
  3. cp -R lib/php/src/* /usr/share/php/Thrift/

Cambiamos al directorio del protocolo de Thrif: ruta-a-thrift/lib/php/src/ext/thrift_protocol.

Instalamos el paquete para construir las extensiones de PHP:

  1. apt-get install php5-dev

Construimos la extensión:

  1. phpize
  2. ./configure --enable-thrift_protocol
  3. make

Copiamos la extensión a la siguiente carpeta (cuidado: dependiendo del sistema el nombre de la carpeta de destino puede variar):

  1. cp modules/thrift_protocol.so /usr/lib/php5/20060613/

Habilitamos el módulo creando el archivo /etc/php5/conf.d/thrift_protocol.ini con el siguiente texto:

  1. extension=thrift_protocol.so

Comprobamos la instalación:

  1. php -i | grep -v "PWD" | grep "thrift_protocol"

Si todo ha ido bien, reiniciamos Apache:

  1. /etc/init.d/apache2 restart

Iniciamos Cassandra:

  1. /opt/cassandra/bin/cassandra -f

Y probamos la consola para comprobar que todo ha ido correctamente:

  1. /opt/cassandra/bin/cassandra-cli -host localhost -port 9160

Debería indicarte algo así:

  1. Connected to: "Test Cluster" on localhost/9160
  2. Welcome to cassandra CLI.

 

INSTALANDO PHPCassa

ACTUALIZACIÓN 20/05/2012
Hace un par de semanas se publicó una nueva versión de phpCassa. Este tutorial está basado en la versión 0.8.a.2 de PHPCassa.

Te recomiendo que te descargues esta versión de PHPCassa para realizar el tutorial.
He actualizado el tutorial a la versión 1.0.a.3 de PHPCassa. Para seguir el tutorial actualizado entra en Cassandra y PHP para desarrolladores SQL.

Bajamos PHPCassa desde github: https://github.com/thobbs/phpcassa

Al descomprimir verás cuatro archivos PHP, copia esos archivos a una carpeta del proyecto en el que estés trabajando.

Abre el archivo “connection.php”, la primera línea será una variable global: $GLOBALS[‘THRIFT_ROOT’], modifica su valor con la ruta hacia los archivos Thrift que copiamos con anterioridad. En mi caso se quedaría así:

  1. <?php
  2. $GLOBALS['THRIFT_ROOT'] = '/usr/share/php/Thrift/';

Con esto finalizamos la instalación de Cassandra para que pueda ser utilizada por PHP.

Os dejo algunas páginas de interés:
CASSANDRA
http://cassandra.apache.org/
http://cassandra.apache.org/download/
http://wiki.apache.org/cassandra/
http://www.apache.org/dist/cassandra/debian/dists/
http://wiki.apache.org/cassandra/DebianPackaging
http://wiki.apache.org/cassandra/CloudConfig
http://cassandra-user-incubator-apache-org.3065146.n2.nabble.com/Cannot-connect-to-Cassandra-td6463518.html
http://sentidoweb.com/2010/03/18/instalar-cassandra-en-ubuntu.php
http://gettingstartedwithcassandra.blogspot.com/2011/06/exception-connecting-to-localhost9160.html
https://wiki.fourkitchens.com/display/PF/Using+Cassandra+with+PHP
http://es.paperblog.com/instalar-cassandra-en-ubuntu-78327/
http://www.unixmen.com/linux-tutorials/960-install-nosql-cassandra-db-in-ubuntu-via-ppa-repository
http://wiki.apache.org/cassandra/ClientOptions

THRIFT
http://thrift.apache.org/

 



PHPCassa
https://github.com/thobbs/phpcassa
http://groups.google.com/group/phpcassa?pli=1

Symfony: El modelo (II)

0

Cuando Symfony construye el modelo, crea una clase de objeto base para cada una de las tablas definidas en schema.yml. Cada una de estas clases contiene una serie de constructores y accesores por defecto en función de la definición de cada columna: los métodos new, getXXX() y setXXX() (donde XXX es el nombre del campo) permiten crear y obtener las propiedades de los objetos:

  1. <?php
  2.  
  3. $articulo = new Articulo();
  4. $articulo->setTitulo('Mi primer artículo');
  5. $articulo->setContenido('Este es mi primer artículo. \n Espero que te guste.');
  6.  
  7. $titulo = $articulo->getTitulo();
  8. $contenido = $articulo->getContenido();

 

Para establecer el valor de varios campos a la vez, se puede utilizar el método fromArray(), que también se genera para cada clase objeto:

  1. <?php
  2.  
  3. $articulo->fromArray(array(
  4. 'titulo' => 'Mi primer artículo',
  5. 'contenido' => 'Este es mi primer artículo. \n Espero que te guste.'
  6. ));
  1. <?php
  2.  
  3. // Relación de "muchos a uno"
  4. echo $comentario->getArticulo()->getTitulo();
  5. => Mi primer artículo
  6. echo $comentario->getArticulo()->getContenido();
  7. => Este es mi primer artículo.
  8. Espero que te guste.
  9.  
  10. // Relación "uno a muchos"
  11. $comentarios = $articulo->getComentarios();

La columna articulo_id de la tabla blog_comentario define implícitamente una clave externa a la tabla blog_articulo. Cada comentario está relacionado con un artículo y un artículo puede tener muchos comentarios. Las clases generadas contienen 5 métodos que traducen esta relación a la forma orientada a objetos, de la siguiente manera:

  • $comentario->getArticulo(): para obtener el objeto Articulo relacionado
  • $comentario->getArticuloId(): para obtener el ID del objeto Articulo relacionado
  • $comentario->setArticulo($articulo): para definir el objeto Articulo relacionado
  • $comentario->setArticuloId($id): para definir el objeto Articulo relacionado a partir de un ID
  • $articulo->getComentarios(): para obtener los objetos Comentario relacionados
  1. <?php
  2.  
  3. $comentario = new Comentario();
  4. $comentario->setAutor('Steve');
  5. $comentario->setContenido('¡Es el mejor artículo que he leído nunca!');
  6.  
  7. // Añadir este comentario al anterior objeto $articulo
  8. $comentario->setArticulo($articulo);
  9.  
  10. // Sintaxis alternativa
  11. // Solo es correcta cuando el objeto artículo ya
  12. // ha sido guardado anteriormente en la base de datos
  13. $comentario->setArticuloId($articulo->getId());

El método getArticulo() devuelve un objeto de tipo Articulo, que permite utilizar el método accesor getTitulo(). Se trata de una alternativa mucho mejor que realizar la unión de las tablas manualmente, ya que esto último necesitaría varias líneas de código (empezando con la llamada al método $comment->getArticuloId()).

La variable $comentarios contiene un array de objetos de tipo Comentario. Se puede mostrar el primer comentario mediante $comentarios[0] o se puede recorrer la colección entera mediante foreach ($comentarios as $comentario).

Al utilizar el constructor new se crea un nuevo objeto, pero no un registro en la tabla blog_articulo. Si se modifica el objeto, tampoco se reflejan esos cambios en la base de datos. Para guardar los datos en la base de datos, se debe invocar el método save() del objeto.

  1. <?php
  2.  
  3. $articulo->save();
  1. <?php
  2.  
  3. foreach ($articulo->getComentarios() as $comentario)
  4. {
  5. $comentario->delete();
  6. }

Si se conoce la clave primaria de un registro concreto, se puede utilizar el método retrieveByPk() de la clase peer para obtener el objeto relacionado.

  1. <?php
  2.  
  3. $articulo = ArticuloPeer::retrieveByPk(7);

En algunos casos, la clave primaria está formada por más de una columna. Es esos casos, el método retrieveByPK() permite indicar varios parámetros, uno para cada columna de la clave primaria.

También se pueden obtener varios objetos a la vez mediante sus claves primarias, invocando el método retrieveByPKs(), que espera como argumento un array de claves primarias.

 

Cuando se quiere obtener más de un registro, se debe utilizar el método doSelect() de la clase peer correspondiente a los objetos que se quieren obtener. Por ejemplo, para obtener objetos de la clase Articulo, se llama al método ArticuloPeer::doSelect().

El primer parámetro del método doSelect() es un objeto de la clase Criteria, que es una clase para definir consultas simples sin utilizar SQL, para conseguir la abstracción de base de datos.

Un objeto Criteria vacío devuelve todos los objetos de la clase.

  1. <?php
  2.  
  3. $c = new Criteria();
  4. $articulos = ArticuloPeer::doSelect($c);
  5.  
  6. // Genera la siguiente consulta SQL
  7. SELECT blog_articulo.ID, blog_articulo.TITLE, blog_articulo.CONTENIDO,
  8. blog_articulo.CREATED_AT
  9. FROM blog_articulo;

Para las selecciones más complejas de objetos, se necesitan equivalentes a las sentencias WHERE, ORDER BY, GROUP BY y demás de SQL. El objeto Criteria dispone de métodos y parámetros para indicar todas estas condiciones. Por ejemplo, para obtener todos los comentarios escritos por el usuario Steve y ordenados por fecha:

  1. <?php
  2.  
  3. $c = new Criteria();
  4. $c->add(ComentarioPeer::AUTOR, 'Steve');
  5. $c->addAscendingOrderByColumn(ComentarioPeer::CREATED_AT);
  6. $comentarios = ComentarioPeer::doSelect($c);
  7.  
  8. // Genera la siguiente consulta SQL
  9. SELECT blog_comentario.ARTICULO_ID, blog_comentario.AUTOR, blog_comentario.CONTENIDO,
  10. blog_comentario.CREATED_AT
  11. FROM blog_comentario
  12. WHERE blog_comentario.autor = 'Steve'
  13. ORDER BY blog_comentario.CREATED_AT ASC;

as constantes de clase que se pasan como parámetros a los métodos add() hacen referencia a los nombres de las propiedades. Su nombre se genera a partir del nombre de las columnas en mayúsculas. Por ejemplo, para indicar la columna contenido de la tabla blog_articulo, se utiliza la constante de clase llamada ArticuloPeer::CONTENIDO.

Otro ejemplo del uso de Criteria con condiciones múltiples. En el ejemplo se obtienen todos los comentarios del usuario Steve en los artículos que contienen la palabra enjoy y además, ordenados por fecha.

 

  1. <?php
  2.  
  3. $c = new Criteria();
  4. $c->add(ComentarioPeer::AUTOR, 'Steve');
  5. $c->addJoin(ComentarioPeer::ARTICULO_ID, ArticuloPeer::ID);
  6. $c->add(ArticuloPeer::CONTENIDO, '%enjoy%', Criteria::LIKE);
  7. $c->addAscendingOrderByColumn(ComentarioPeer::CREATED_AT);
  8. $comentarios = ComentarioPeer::doSelect($c);
  9.  
  10. // Genera la siguiente consulta SQL
  11. SELECT blog_comentario.ID, blog_comentario.ARTICULO_ID, blog_comentario.AUTOR,
  12. blog_comentario.CONTENIDO, blog_comentario.CREATED_AT
  13. FROM blog_comentario, blog_articulo
  14. WHERE blog_comentario.AUTOR = 'Steve'
  15. AND blog_articulo.CONTENIDO LIKE '%enjoy%'
  16. AND blog_comentario.ARTICULO_ID = blog_articulo.ID
  17. ORDER BY blog_comentario.CREATED_AT ASC

Además del método doSelect(), todas las clases peer tienen un método llamado doCount(), que simplemente cuenta el número de registros que satisfacen las condiciones pasadas como parámetro y devuelve ese número como un entero.

Las clases peer también incluyen métodos doDelete(), doInsert() y doUpdate() (todos ellos requieren como parámetro un objeto de tipo Criteria).

Por último, si solo se quiere obtener el primer objeto, se puede reemplazar el método doSelect() por doSelectOne(). Es muy útil cuando se sabe que las condiciones de Criteria solo van a devolver un resultado, y su ventaja es que el método devuelve directamente un objeto en vez de un array de objetos.

A veces, no es necesario obtener los objetos, sino que solo son necesarios algunos datos calculados por la base de datos. Por ejemplo, para obtener la fecha de creación de todos los artículos, no tiene sentido obtener todos los artículos y después recorrer el array de los resultados.

Para realizar consultas a la base de datos con PDO, es necesario realizar los siguientes pasos:

  • Obtener la conexión con la base de datos.
  • Construir la consulta.
  • Crear una sentencia con esa consulta.
  • Iterar el result set que devuelve la ejecución de la sentencia.
  1. <?php
  2.  
  3. conexion = Propel::getConnection();
  4. $consulta = 'SELECT MAX(%s) AS max FROM %s';
  5. $consulta = sprintf($consulta, ArticuloPeer::CREATED_AT, ArticuloPeer::TABLE_NAME);
  6. $sentencia = $conexion->prepare($consulta);
  7. $sentencia->execute();
  8. $resultset = $sentencia->fetch(PDO::FETCH_OBJ);
  9. $max = $resultset->max;

Normalmente, cuando una tabla tiene una columna llamada created_at, se utiliza para almacenar un timestamp de la fecha de creación del registro. La misma idea se aplica a las columnas updated_at, cuyo valor se debe actualizar cada vez que se actualiza el propio registro.

La buena noticia es que Symfony reconoce estos nombres de columna y se ocupa de actualizar su valor de forma automática. No es necesario establecer manualmente el valor de las columnas created_at y updated_at; se actualizan automáticamente. Lo mismo se aplica a las columnas llamadas created_on y updated_on.

  1. <?php
  2.  
  3. $comentario = new Comentario();
  4. $comentario->setAutor('Steve');
  5. $comentario->save();
  6.  
  7. // Muestra la fecha de creación
  8. echo $comentario->getCreatedAt();
  9. => [fecha de la operación INSERT de la base de datos]

Además, los getters de las columnas de fechas permiten indicar el formato de la fecha como argumento:

  1. <?php
  2.  
  3. echo $comentario->getCreatedAt('Y-m-d');

 

Ir arriba