El día que conocí a Couchbase, digamos que, no fue el mejor de los encuentros, incluso puedo decir que fue totalmente lo opuesto a lo que llaman “amor a primera vista”. Y es que las condiciones en las que nos presentaron no fueron las más favorables.

Entre mi inexperiencia y la poca documentación que tenía, me topé con una diversidad de situaciones que nunca había experimentado en cuanto a BBDD se refiere.

Sin embargo, aunque el primer encuentro no fue el soñado, no quedaba otra opción que seguir en el proceso de conocer qué había en las profundidades de la base de datos NoSQL, que según sus creadores “es una de las más poderosas del mundo”.

Y sí, aunque fue duro el comienzo, poco a poco he ido descubriendo sus bondades, hasta tal el punto de considerarla personalmente como una excelente alternativa en relación a las bases de datos orientadas a documentos (he de confesar que al principio no era así).

Antes de adentrarnos en el análisis de Couchbase, comencemos por su definición.

Observación: Importante aclarar, que no pretendo contar todas las características de Couchbase al máximo nivel de detalle porque, honestamente, esto daría para escribir un libro entero y no es el objetivo de este post. Sin embargo, mi intención principal es presentaros aquellos puntos que me han llamando más la atención y animaros a que profundicéis en el tema y que tengáis vuestra propia experiencia con dicha base de datos.

Definición

Couchbase es una base de datos orientada a documentos (basada en documentos JSON), “NoSQL”, distribuida, escalable y que centra su potencial en la clave/valor. Entre sus principales características encontramos que:

A diferencia de otras bases de datos orientadas a documentos, Couchbase soporta los JOINs en sus consultas, esto es posible a través de su propio lenguaje de consultas N1QL, similar al SQL estándar en cuanto a notación con una extensión de funcionalidades sobre documentos JSON.

Su origen viene dado de la unión de los productos Membase y Apache CouchDB. Sus creadores buscaban sacar provecho de las principales cualidades de cada uno de ellos y, tras la fusión, conseguir el máximo rendimiento de una base de datos en memoria (Membase) bajo una arquitectura distribuida (CouchDB).

Aspectos interesantes de su arquitectura

En cuanto arquitectura y servicios se refiere, Couchbase ofrece una gran flexibilidad, ya que cualquier servicio se puede implementar de manera flexible en los recursos de hardware disponibles, proporcionando escalado multidimensional (Multidimensional Scaling - MDS), por lo que un clúster se puede ajustar para un manejo óptimo de las cargas de trabajo emergentes.

Entre los servicios básicos y elementales encontramos los siguientes:

Tal como mencioné anteriormente, la disposición de la arquitectura puede ser lo bastante flexible como para que la organización estructural de los servicios pueda hacerse en función, bien sea de los recursos de hardware o bien de forma en que pueda explotarse la capacidad máxima de cada servicio según sea el caso de uso.

Es decir, podríamos potenciar la capacidad de ingesta (escritura) del sistema si el caso de uso lo requiriera, o por el contrario potenciar la de lectura si fuera más óptimo.

A continuación os presento un breve ejemplo de cómo puede ser la organización de los servicios:

En el ejemplo anterior encontramos un clúster de cinco nodos con una distribución homogénea, donde los servicios se encuentran desplegados en todos y cada uno de los nodos de nuestro clúster.

Observamos que, con dicha arquitectura, el mayor potencial está en el balance de cargas de trabajo y la alta disponibilidad de los recursos, pero digamos que es un buen esquema para entornos más experimentales o entornos no productivos. Os preguntaréis, ¿por qué digo esto?

Sí, ciertamente el balanceo de carga y la alta disponibilidad son un gran punto a favor en cualquier situación, y más en entornos productivos, el tema aquí está en que en una arquitectura de este tipo los servicios no podrán disponer de manera dedicada de todos los recursos del sistema, compitiendo siempre por los mismos e, incluso, llegando al punto de ‘estorbarse' cuando hay picos de carga de trabajo.

Otra desventaja del modelo homogéneo está en que bajo este esquema no se permite el escalado horizontal y vertical de un solo servicio.

Por ejemplo, si en nuestra operativa detectamos la necesidad de incrementar los recursos de memoria del servicio de índices, dada la disposición que ofrece Couchbase, esto no sería posible sin afectar al resto de servicios, ya que nos obliga a añadir otro nodo de las mismas características (exactamente igual al nivel de servicios disponibles y recursos reservados) que el resto de nodos que conforman el clúster.

Esto, por otro lado, nos dice que debemos intentar ser mucho más precisos al momento de elegir los recursos y dimensión de nuestro clúster (principalmente en fases iniciales), ya que una vez definido el primer nodo, luego hacer algún ajuste sobre el clúster se puede convertir en una tarea bastante tediosa.

Ahora bien, Couchbase también nos ofrece otro tipo de distribución a nivel de arquitectura en la cual los servicios y nodos se puede establecer y gestionar de manera independiente. ¿Qué quiere decir esto? Pues muy sencillo, que cada servicio puede ser distribuido y desplegado de manera que sus recursos se aprovisionan en función del caso de uso.

Veámos el siguiente ejemplo:

Se puede observar claramente que, a diferencia de la distribución homogénea, en este caso, en un clúster de las misma dimensiones (y asumamos que de recursos también), los servicios pueden contar con una dedicación exclusiva, sin compartir y competir por la máquina donde se encuentran desplegados.

Entonces, en el caso en que necesitáramos más recursos de algún tipo de servicio en particular, nos bastaría con agregar un nuevo nodo al clúster con el servicio deseado. El escalado horizontal sería mucho más sencillo de gestionar.

En este punto estaréis pensando que en el ejemplo anterior nos falla algo y, efectivamente, tenéis razón. En el ejemplo no contamos con la alta disponibilidad para los servicios de índices y de consulta, sin embargo, esto solo era un ejemplo para mostraros cómo cambia la cosa cuando trabajamos bajo la distribución independiente.

Ciertamente, en este caso, podemos hacer un par de ajustes para que un clúster con distribución independiente cobre más sentido en un entorno productivo.

Una primera mejora que podemos hacer para el caso anterior es que los servicios de índices y consultas compartan recursos. Y, aunque no tengamos la disposición de exclusiva de los nodos, ganaremos al conseguir alta disponibilidad y balanceo de carga.

Además, es importante destacar que en Couchbase el servicio de consultas (Query Service) no requiere reservar memoria RAM, en comparación al resto de servicios, con lo que no competiría con el servicio de índices en cuanto a memoria se refiere, pero no así con respecto a la CPU que sí sería compartida.

Esto, en cualquier caso, sería un mal menor si el volumen de datos y las operaciones por segundo de consulta requeridas en nuestro caso de uso son perfectamente soportados nuestro clúster.

Otro punto a favor que tiene la distribución independiente es que no todos los nodos tienen por qué ser del mismo tamaño ni tampoco de las mismas características.

Esto quiere decir que la selección de la capacidad de nuestros nodos para la distribución de los servicios puede hacerse acorde a la volumetría de datos y a la carga de trabajo estimada para el caso de uso.

Con lo cual, una segunda mejora que podríamos hacer sobre el ejemplo anterior es que los nodos con servicios de índices y consultas sean de mayor capacidad, es decir, que sean más potentes en cuanto a memoria y CPU (que es lo que más requieren estos servicios), quedando de la siguiente manera:

Ahora bien, hemos observado los puntos positivos del modelo de escalado independiente, pero no todo es color de rosa, y por ello es necesario puntualizar que, dicho modelo solo es posible implementarlo siempre que se trabaje bajo la versión Enterprise, lo cual implica que debe pagarse la licencia del producto Couchbase Server por cada nodo que conforma nuestro cluster.

Después de haber analizado algunas de las ventajas y desventajas que nos ofrecen los dos tipos de distribución dentro de la arquitectura de Couchbase (Homogénea e Independiente), pasaremos a analizar otros factores que juegan un papel importante a la hora de sacar el máximo partido de nuestra base de datos.

El modelo de datos y el modelo de acceso: papel fundamental

Una de las máximas de Couchbase es que, en la medida de lo posible, todas las consultas deben elaborarse de manera tal que las mismas ataquen directamente a los servicios de datos, a través de lo que se conoce como clave/valor.

Y es que esta es la mejor manera (la forma más rápida que existe en Couchbase y donde está su mayor potencia) de obtener los datos, debido a que no intervienen el resto de servicios (Query Service / Index Service).

A continuación listamos algunas consideraciones que debemos tener muy en cuenta al momento de definir el modelo de datos:

Observación: Esta es solo una pequeña selección de una extensa lista recomendaciones y buenas prácticas referentes al modelado de los datos. Es un tema que tiene mucha más tela para cortar, pero se escapa del alcance de este post.

Tal como hemos mencionado anteriormente, en Couchbase la modalidad de acceso a los datos con mejor rendimiento es a través de la clave/valor.

Por tal motivo, es altamente recomendable definir nuestras claves (document id), de tal forma que la mayoría de los accesos a los datos sea directamente a través de la clave, evitando pasar por todas las fases que componen la ejecución de una consulta (que en ocasiones pueden ser lo bastantes complejas según el caso de uso, por ejemplo, cuando usamos la cláusula JOIN); así como también la comunicación intra-servicios, reduciendo las latencias.

Couchbase provee su propio lenguaje de consultas, N1QL, cuyo objetivo es satisfacer las necesidades de consulta de bases de datos distribuidas orientadas a documentos. Además, está basado en el estándar SQL, pero con una extensión de funcionalidades sobre documentos JSON.

El modelo de datos N1QL deriva su nombre de la primera forma normal que es un superconjunto y generalización de la primera forma normal relacional (1NF).

Como en otras bases de datos, en Couchbase es posible definir índices que permitan el acceso a los datos a través de las consultas que realizamos en N1QL.

Tipos de índices en Couchbase:

Cuando un índice incluye los valores de todos los campos especificados en la consulta, el índice cubre la consulta y no requiere un paso adicional para obtener los valores del servicio de datos. En este caso, se denomina índice de cobertura y la consulta se denomina consulta cubierta. Como resultado, las consultas cubiertas presentan latencias más bajas y ofrecen un mejor rendimiento.

Caso práctico

A continuación un pequeño ejemplo de cómo definir un “document id” de manera que podamos potenciar el acceso a través de la clave.

Escenario

Supongamos que nuestro caso de uso se trata de una aplicación de back-office que gestiona un catálogo de productos a través de una web interna, donde es posible buscar y listar productos según una serie de filtros. Los productos, además de la categoría a la que pertenecen, cuentan con otros campos que definen su detalle.

Documento base

En el ejemplo podemos observar que el document_id se ha definido como campo compuesto por el tipo de producto, la categoría y su código único. Os preguntaréis, ¿qué se gana con esto?

La respuesta es muy sencilla. Definir la clave de esta manera nos proporciona la posibilidad de que, al momento de aplicar el filtro en cascada desde la web, podamos conformar el camino directo al producto.

Esto nos permite obtener el documento a través de la cláusula USE KEYS, que es el modo de acceso a los datos en clave/valor mediante sentencias N1QL, sin la intervención del servicio de índices y registrando latencias bastante bajas.

Es importante aclarar que es posible definir una consulta (query) para obtener el valor del documento anterior.

Sin embargo, para ello, sería necesario definir un índice secundario adecuado que cumpla con las condiciones de búsqueda (se dice adecuado pensando en su rendimiento).

Esto también sería posible con un índice primario, pero sacrificando los tiempos de respuesta por todo lo explicado en líneas anteriores.

En el siguiente ejemplo puede observarse que es estrictamente necesario la creación de un índice (primario o secundario) si no accedemos al dato mediante clave/valor.

Ya para concluir os presento una tabla resumen donde se ordenan las modalidades de acceso a los datos según su rendimiento, comenzando por la más rápida.

Conclusión

Cuando se habla de mejorar el rendimiento y latencias de una base de datos, plataforma, aplicación o sistema, por lo general suele asociarse automáticamente con el incremento de sus capacidades principalmente de hardware (memoria RAM, CPUs, disco, etc.).

Sin embargo, en muchas ocasiones, la solución a nuestros problemas de rendimiento no solo está detrás de tener más hierro (sin duda, esto ayuda), sino también que una incorrecta configuración, un mal diseño o el empleo de malas prácticas jugará en nuestra contra, impidiendo que podamos sacar el máximo partido a nuestros sistemas o aplicaciones.

Además, no olvidemos que, para acercarnos a la mejor configuración, el diseño más ajustado y las buenas prácticas aplicables, es deseable conocer el producto. En en nuestro caso, el Couchbase y sus puntos característicos, los fuertes y los débiles.

Y es que mejorar el rendimiento no siempre significa "más madera".

Cuéntanos qué te parece.

Enviar.

Los comentarios serán moderados. Serán visibles si aportan un argumento constructivo. Si no estás de acuerdo con algún punto, por favor, muestra tus opiniones de manera educada.