¿Cuándo usar Cassandra? ¿Cuándo usar MongoDB?

¿Qué sistema de base de datos NoSQL debemos usar para nuestra aplicación? ¿Cuándo debemos usar Cassandra? ¿Cuándo debemos usar Mongodb? ¿Cuál es mejor?

No pretendo hacer una comparación entre base de datos NoSQL y una base de datos relacional como MySQL. Cada una tiene sus ventajas y desventajas; además tienen objetivos diferentes. Tampoco hablaremos del poder de las base de datos NoSQL, ni lo grandioso que puede ser Redis para nuestra aplicación.

En esta publicación, compartiré información que será de ayuda para comprender que es Cassandra, y en que se diferencia de MongoDB; además de conocer como funciona MongoDB y  que lo hace diferente de Cassandra.

¿Cuál es mejor?….en realidad ambos son excelentes base de datos NoSQL. ¿Y entonces cuándo debo usar MongoDB? ¿Cuándo debo usar Cassandra?…dependerá mucho de la necesidad de tu aplicación, hay muchas variables que debes analizar, por ejemplo, cantidad de escrituras vs lecturas en la base de datos, almacenamiento constante de información, escalabilidad, velocidad de respuesta, incrementos exponenciales en el consumo de información, datos en constante actualización o bajo porcentaje de modificación, entre otras cosas.

Ambos sistemas de base de datos NoSQL tienen varias fortalezas en común; una de ellas es el poder que tienen para manejar grandes, pero grandes cantidades de datos no estructurados y tener la capacidad de escalar horizontalmente.

¿Puedo escalar mi base de datos con Cassandra y MongoDB?

Si, y no serás el primero en querer hacerlo, Cassandra es la base de datos NoSQL de Instagram, en la cual se almacena más de 80 millones de fotos cargadas todos los días. MongoDB es parte del stack tecnológico de Google Compute Engine.


¿Cómo se almacena la información en ambos sistemas de base de datos?

Cassandra almacena la información en “Columns Families” que son objetos de base de datos similares a las tablas de un sistema de base de datos relacional (como MySQL), las cuales contienen filas y columnas, cada fila con una clave única. A diferencia de un sistema de base de datos relacional, todas las filas de una tabla no están obligadas a tener las mismas columnas. Estas columnas también se pueden agregar sobre la marcha y se accede a ellas utilizando el Lenguaje de Consulta de Cassandra (CQL= Cassandra Query Language). Mientras que CQL es similar a SQL en sintaxis, Cassandra no es relacional, por lo que tiene diferentes formas de almacenar y recuperar datos.

MongoDB almacena la información en documentos similares a JSON que pueden tener estructuras variadas. Utiliza un lenguaje propio de consulta para permitir el acceso a los datos almacenados. Como no tiene esquemas, puede crear documentos sin tener que crear primero la estructura del documento.

¿Quienes usan estas base de datos?

Ambas bases de datos tienen miles de seguidores y grandes organizaciones tecnológicas que confían en ellas.

Cassandra, escrita en Java, fue liberada en el 2008, ha sido utilizada por muchas organizaciones, incluidas AppScale, Constant Contact, Digg, Facebook, Twitter, IBM, Instagram, Spotify, Netflix y Reddit.

MongoDB, escrita en C++, fue liberada en el 2009, ha sido utilizado por muchas organizaciones, entre ellas. Google, UPS, Facebook, Cisco, eBay, BOSH, Adobe, SAP, Forbes y muchos más. Puedes consultar la lista completa aquí.

¿Cuál es la sintaxis para consultar información?

Por ejemplo, si queremos consultar registros de una tabla de Productos.

Cassandra: SELECT * FROM products

MongoDB: db.products.find()

Insertar registros a una tabla de Personas (Contactos).

Cassandra: INSERT INTO contacts (contact_id,name,last_name) VALUES (‘c00001′,’Gonzalo’,’Chacaltana Buleje’)

MongoDB: db.contacts.insert({contact_id:’c00001′,name:’Gonzalo’,last_name:’Chacaltana Buleje’})

Actualizando registros en una tabla de Productos.

Cassandra: UPDATE products SET stock=2000 WHERE product_name=’Milk’

MongoDB: db.products.update.({product_name:’Milk’},{$set:{stock:2000}})

¿Cómo funciona la replicación en estas bases de datos?

Cassandra replica desde el primer momento. Solo le dice la cantidad de nodos a los que debe copiar sus datos y se  ocupa del resto del proceso de replicación.

Cassandra permite tener múltiples bases de datos maestras y en caso de la pérdida de un nodo, Cassandra podrá escribir en el resto de base de datos (Cluster). Esta característica permite una mejor tolerancia a fallas, evitando perder tiempo de inactivividad como podría ocurrir con MongoDB.

MongoDB tiene una replicación incorporada con auto-elecciones, es decir, con MongoDB podrás configurar una base de datos secundaria que se puede convertir de manera automática en una base de datos principal si la base de datos principal (inicial) deja de estar disponible. Sin embargo, MongoDB requiere una cierta configuración (y tal vez un poco de ayuda de soporte) para hacer la replicación. MongoDB tiene conjuntos de réplicas donde un miembro es el primario y todos los demás tienen un rol secundario (Modelo Master-Slave). Las lecturas y escrituras se confirman primero en la réplica principal y luego se replican en las réplicas secundarias.

MongoDB tiene una sola base de datos maestra.

Mientras que el proceso de auto-elección ocurre automáticamente, puede tomar de 10 a 40 segundos para que ocurra. Mientras esto sucede, no puede escribir en el conjunto de réplicas.

¿Quién está actualmente detrás de estas bases de datos?

En el caso de Cassandra: Avinash Lakshman y Prashant Malik desarrollaron Cassandra en Facebook para la función de búsqueda en la bandeja de entrada de Facebook. Facebook lanzó Cassandra en julio de 2008 como un proyecto de código abierto. Apache Software Foundation se encuentra actualmente detrás de la base de datos.

MongoDB se inició en 2007 por la empresa de software 10gen, que creó el producto basado en la palabra “humongous”. En 2009, fue lanzado, y 10gen más tarde cambió el nombre de su compañía a MongoDB, Inc. MongoDB, Inc. proporciona el desarrollo del software y vende su solución empresarial.

¿Qué base de datos es adecuada para mi aplicación?

Una de las mayores fortalezas de Cassandra es su capacidad de escalar sin dejar de ser confiable. Es posible implementar Cassandra en múltiples servidores integrados sin mucho trabajo adicional. Parte de esto se debe a que Cassandra maneja la replicación con una configuración mínima, lo que facilita la configuración.

Si necesita una base de datos que sea fácil de instalar y mantener, independientemente de cuánto crezca su base de datos, Cassandra puede ser una buena opción.

Si trabajas en una industria en la que necesitas un rápido crecimiento de tu base de datos, Cassandra ofrece un crecimiento más fácil y rápido que MongoDB.

MongoDB puede ser una gran opción si necesitas escalabilidad y almacenamiento en caché para análisis en tiempo real; sin embargo, no está diseñado para datos transaccionales.

MongoDB se usa con frecuencia para aplicaciones móviles, administración de contenido, análisis en tiempo real y aplicaciones relacionadas con el IoT (Internet de las cosas). Si tiene una situación en la que no tiene una definición de esquema clara, MongoDB puede ser una buena opción.

Si tienes una situación en la que estás des-normalizando el esquema de tu base de datos, los documentos MongoDB se pueden usar para almacenar los datos no estructurados de una manera que es más fácil de actualizar. En una situación donde la carga de escritura es alta, MongoDB puede ser una buena opción. Ofrece una alta tasa de inserción.

Y entonces ¿Con cuál de las base de datos utilizarías para tu proyecto?

Introducción al diseño de una API HTTP (Parte 4 de 4): Estándares

Este cuarto y último artículo hace un breve resumen sobre los distintos estándares aplicados en el diseño de una API HTTP para el intercambio de información.

Simple Response

Uno de los objetivos de nuestra API es responder con información que entienda el consumidor. Muchas veces, solo nos bastará con responder con solo el recurso solicitado o una matriz de recursos solicitados. Sin embargo, también hay metadatos que queremos proporcionar a nuestros consumidores. Una alternativa es  usar los HTTP Headers, los cuales son usados para proporcionar metadatos, pero por lo general no es lo suficientemente potente como para transmitir todo lo que el consumidor necesita saber del recurso.

Unos de los casos que se dan muy a menudo, son los mensajes de error que debemos proporcionar al consumidor de nuestra API. Si bien, podemos suministrar un código de estado 4XX o 5XX cuando falla una solicitud, pero ¿Cómo podemos ser más específicos? ¿Cómo hacemos para que nuestro cliente sepa si una solicitud es un error y cómo obtener mayor información del error?.

Ante este escenario, podemos responder con un objeto principal a los datos reales (en del HTTP Response). Nos referimos a responder con un objeto JSON estandarizado como un “sobre” (respuesta simple), ya que envuelve los datos importantes. Por ejemplo:

En el ejemplo, se observa dos propiedades de error. El primero, “error“, es un código de error analizable por una aplicación (consumidor). Hay APIs que optan por usar valores numéricos en vez de un valor de cadena, pero ¿por qué usar un formato numérico ilegible cuando lo tratan como una cadena? También queremos una cadena separada legible por humanos, como por ejemplo la propiedad “error_description“. Esta cadena podría traducirse teóricamente para coincidir con el Accept-Language del Request y mostrarle a un usuario final.

Si la respuesta (HTTP Response) fuera exitosa, podemos agregar propiedades adicionales como estas:

En este caso, todavía tenemos la propiedad de “error” y “error_description“, pero dado que no hay un error, lo configuramos en nulo (null). La propiedad “data” contiene el contenido solicitado por el consumidor, en este caso, el consumidor solicita una recopilación de datos (por ejemplo: estudiantes), por lo que proporcionamos una serie de recursos en esa colección (id y name). Finalmente tenemos dos propiedades de metadatos adicionales, “offset” y “per_page“, que le informa al consumidor sobre la respuesta. En este caso, el cliente ha solicitado la segunda página de resultados con 10 entradas por página, por lo que básicamente respondemos con esos datos para el contexto.

JSON API

API JSON es un estándar para el intercambio de información entre aplicaciones, que recomienda buenas prácticas para eliminar redundancias de datos, a la hora de devolver información a nuestros consumidores. Por citar un ejemplo, tenemos una API que representa a una colección de libros de una reconocida cadena de librerías. Cada libro tendrá un contenido único, es decir, tendrá un título, un código (identificador) y un precio. Sin embargo, cada libro tendrá información potencialmente redundante, como la información del autor.

Por lo general, ante estas situaciones, una API devuelve la información del autor de forma redundante por cada libro. Es probable que existan muchos libros cuyo autor es el mismo, por lo tanto, estaríamos enviando un montón de contenido al consumidor. El estándar API JSON nos permite, en cambio, definir relaciones entre diferentes tipos de recursos, eliminando así las redundancias. Mira el siguiente ejemplo:

GraphQL

GraphQL es un estándar API desarrollado por Facebook. Incluye un formato personalizado para consultar datos. Normalmente, las respuestas se envían en formato JSON. El formato de consulta requiere que el consumidor especifique todos los atributos que desea en la respuesta. Esto nació de la necesidad de que las aplicaciones clientes móviles obtengan solo datos importantes, desperdiciando menos bytes en la transferencia de información.

Otra característica de GraphQL es que los atributos solicitados en la respuesta pueden correlacionarse con datos de diferentes colecciones. Esto hace que GraphQL sea particularmente atractivo cuando se construyen componentes estructurales (facades), servicios que consumen datos de otros servicios. GraphQL puede realizar las agregaciones necesarias en una única solicitud (HTTP Request), evitando que el cliente tenga que realizar múltiples solicitudes a diferentes colecciones.

Las solicitudes generalmente usan un endpoint HTTP único, con el cuerpo recibido a través de POST. GraphQL NO es una práctica RESTful de HTTP, y en realidad se puede usar completamente por separado de HTTP. Este es un ejemplo de una consulta GraphQL:

Este es un ejemplo de la respuesta correlacionada (HTTP Response):

MessagePack

MessagePack se puede considerar como una representación binaria 1:1 de JSON. Cualquier documento JSON se puede representar como MessagePack, lo que significa que se puede usar con API JSON o GraphQL. Se elimina cualquier espacio en blanco superfluo y también se eliminan algunas otras redundancias, como los caracteres de comillas y dos puntos. La representación binaria suele ser más pequeña y puede ser más rápida de serializar y deserializar.

Observa el siguiente documento. Este archivo tiene 109 bytes (sin contar espacios en blanco). Es un objeto con tres propiedades, la primera es un identificador, la segunda una cadena y la tercera una matriz de dos valores numéricos:

El siguiente es el mismo contenido del archivo anterior, pero en formato MessagePack reducido a 78 bytes (72% del anterior).

JSON RPC (Remote Procedure Call)

JSON RPC es un paradigma muy diferente del HTTP RESTful que hemos estado viendo en todas estas publicaciones. En lugar de abstraer los datos en recursos y realizar operaciones CRUD en ellos, simplemente puede exponer las funciones y sus parámetros y permitir que los clientes llamen a estas funciones semi-directamente. Este patrón se llama RPC. JSON RPC es entonces

De forma similar a GraphQL, si usa estas solicitudes a través de HTTP, probablemente use un endpoint único, acepte las solicitudes a través de una solicitud POST y responda. JSON RPC también puede funcionar completamente fuera de HTTP, por ejemplo con TCP o IPC (Inter-Process Communications).

Aquí hay un ejemplo de una solicitud JSON RPC. El documento es muy simple; la solicitud requiere un número de versión (propiedad “jsonrpc“), un identificador (para correlacionar los request con los response, ya que no estamos casados con HTTP). También nombramos el método RPC (propiedad “method“) que queremos ejecutar y proporcionamos argumentos en la propiedad “params”. Los parametros pueden ser una matriz o un objeto, correlacionando a parámetros de función normal o parámetros nombrados, respectivamente.

La respuesta (HTTP Response) también contiene una versión y un identificador correspondiente a la solicitud (HTTP Request). La propiedad importante es “result” que contiene el resultado de la operación.

Artículos relacionados:

 

Fuentes: