Alex Sirbu Jefe de equipo de I+D en Lentiq, cuenta con siete años de experiencia en arquitectura y creación de sistemas distribuidos fiables.
Lentiq es una startup de data lake-as-a-service multicloud basada en Kubernetes, lo que significa que nos ganamos la vida gestionando a diario los datos y flujos de trabajo de otras personas. Para conseguirlo correctamente, necesitamos una base de datos rápida, fiable y escalable para almacenar toda nuestra información interna que, además, nos permita implementar una arquitectura orientada a microservicios. Couchbase ha demostrado una y otra vez que cubre todos nuestros requisitos, y ha sido nuestra base de datos de elección desde que comenzó nuestro proyecto. Así, a continuación presentamos nuestra historia con la integración y el uso de Couchbase como única capa de almacenamiento interno persistente en Lentiq.
Elección
¿Por qué elegimos Couchbase en primer lugar? La respuesta proviene de nuestra experiencia previa con él. Nuestro equipo pasó del proyecto de nube desnuda en Bigstep nuestra empresa matriz, al nuevo proyecto Lentiq. Algunos de nuestros colegas trabajaron en el producto Couchbase utilizado por Bigstep, realizando pruebas de rendimiento (que demostraron lo bien que funcionaba), así como utilizándolo realmente en algún momento como caché frente a una base de datos relacional más lenta. Esta experiencia previa con Couchbase resultó valiosa cuando tuvimos que elegir nuestra capa de almacenamiento interno para Lentiq.
Un factor importante en nuestra selección fue la arquitectura del nuevo producto. Al dividir la aplicación en varios microservicios desacoplados, necesitábamos aplicar el mismo principio de desacoplamiento a la capa de base de datos. Esto reforzaría aún más la separación de intereses entre los módulos, junto con el hecho de que la única forma de que los microservicios obtuvieran información de otros servicios sería a través de interfaces expuestas: no se permitía eludir la base de datos. También necesitábamos movernos rápido y experimentar, y no tener que lidiar con esquemas estrictos, así que decidimos tomar la ruta NoSQL para este proyecto. Y, por último, pero no por ello menos importante, como el proyecto iba a estar escrito en Java y Spring, el soporte para interactuar fácilmente con la base de datos era otro factor esencial.
Así pues, teniendo en cuenta todos los requisitos y viendo también que nuestro viejo amigo Couchbase cumplía todos los requisitos, decidimos utilizar Couchbase para nuestro MVP, ¡y desde entonces no hemos cambiado de opinión!
Arquitectura
Los dos últimos requisitos son bastante sencillos, pero ¿cómo utilizamos Couchbase para lograr el primer requisito: una arquitectura basada en microservicios?
La solución obvia era asignar un bucket por microservicio, dando a cada uno un usuario separado que sólo pudiera acceder a su bucket específico, con las credenciales de acceso al cluster dadas a cada servicio al arrancar. Fácil, ¿verdad? Mediante el uso de módulos desacoplados, nos las arreglamos para (en su mayoría) tener sólo un tipo de objeto con el que cada microservicio trabaja en estrecha colaboración. Este objeto específico tiene campos públicos (externos, accesibles por microservicios externos) e internos. Todos los campos se guardan dentro del cubo, pero el objeto se limpia y se expone sólo con sus campos públicos a través de las interfaces externas de su propietario.
Nuestra asignación también nos ayudó con el escalado y la fiabilidad. Como al principio teníamos pocos microservicios, pusimos todos los buckets dentro del mismo clúster de Couchbase. A medida que añadimos más y más, los agrupamos en función del tráfico y el tamaño de los objetos y los dividimos en varios clústeres, aislándolos aún más y permitiendo un escalado independiente.
Consultas
Utilizando el Datos de Spring Biblioteca Couchbase , conectarse y utilizar Couchbase para leer y escribir datos se convierte en algo sencillo.
Las operaciones comunes de lectura y escritura son proporcionadas por CouchbaseRepositories y CouchbaseTemplates (insert, update, delete, findById). Lo que nos ayuda mucho es la forma en que estas operaciones básicas se pueden ampliar. Por ejemplo, la consulta de todos los entornos de proyecto dentro del mini-lago de datos que llamamos pool de datos se hace simplemente teniendo la siguiente clase de repositorio:
|
1 2 3 4 5 6 |
@Repositorio @N1qlPrimaryIndexed @VerIndexado(designDoc = "Proyecto) público interfaz Depósito de proyectos extiende CouchbaseRepository<Proyecto, Cadena> { Lista<Proyecto> findByDatapoolName(Cadena datapoolName); } |
Para realizar consultas más complejas (por ejemplo, buscar un valor dentro de una matriz), utilice la función Lenguaje de consulta N1Q1 es tan fácil como añadir una anotación para la función dada. El siguiente ejemplo devuelve todos los conjuntos de datos con un estado determinado e identifica cuáles contienen la visibilidad requerida en su matriz de visibilidad:
|
1 2 3 4 5 6 7 |
@Consulta( "#{#n1ql.selectEntity}" + "WHERE #{#n1ql.filter}" + "AND status = $1 " + "AND ARRAY_CONTAINS(#{#visibilidades}, visibilidad)" ) ArrayList<Conjunto de datos> findByStatus(Cadena estado, Cadena visibilidades); |
El campo n1q1.filter se rellena automáticamente con "_class=**SpecifiedClassForRepository**" para devolver sólo el tipo de objetos solicitado, lo que permite almacenar varios tipos de objetos dentro del mismo cubo, sin tener que hacer nada especial.
Bloqueo
No sólo utilizamos Couchbase para almacenar y consultar datos, sino también para realizar el bloqueo de nuestros servicios.
Un ejemplo en el que necesitamos bloqueo es cuando un cliente quiere crear una nueva aplicación para crujir algunos datos, y tenemos que comprobar si el usuario tiene recursos suficientes para arrancar la aplicación. No parece una necesidad directa de bloqueo, ¿verdad? Bueno, como nuestro entorno es colaborativo y varias personas pueden trabajar en el mismo proyecto, varios clientes pueden crear aplicaciones dentro del mismo entorno al mismo tiempo. Por lo tanto, si no utilizamos el bloqueo para ese entorno en particular, aunque se arranque la aplicación de cada individuo, es posible que al intentar arrancarlas al mismo tiempo, se excedan los recursos físicos reales y una aplicación -o ambas, si las aplicaciones tienen varios componentes- pueda fallar. Por lo tanto, el requisito es realizar la comprobación mientras se mantiene un bloqueo, hasta que la nueva aplicación pueda ser tenida en cuenta por la otra operación de creación.
¿Cuál es entonces nuestra solución de bloqueo? El bloqueo pesimista, en forma de getAndLock y unlock, que bloquea el acceso a un documento dado mientras se mantiene el bloqueo. He aquí un ejemplo simplificado:
|
1 2 3 4 5 6 7 8 |
Cadena lockName = generateLockNameForEnvironment(); JsonDocument cierre = couchbaseBucket.getAndLock(lockName); pruebe{ performPhysicalResourcesCheckForApplication(); } finalmente{ couchbaseBucket.desbloquear(cierre); } |
El principal problema que encontramos con este enfoque es que para que getAndLock funcione realmente todo el tiempo, el documento que bloquea debe existir previamente, y no hay getOrCreateAndLock atómico. Para solucionarlo, como el bloqueo está vinculado al entorno al que bloquea el acceso, hemos integrado la creación y eliminación del documento de bloqueo con los flujos de creación y eliminación del entorno. De este modo, el documento ya se genera cuando un cliente llega a crear una aplicación (ya que el proceso completo de creación del entorno debe haber finalizado antes), por lo que el bloqueo puede realizarse correctamente. Como ventaja añadida, una vez que se elimina el entorno concreto, el documento también se elimina y no se queda en el cubo sin hacer nada.
Conclusión
En Lentiq, sabemos que tener una capa de almacenamiento fiable y rápida es de suma importancia tanto para nuestros clientes como para nuestros servicios internos. Couchbase nos ha demostrado que tomamos la decisión correcta cuando la elegimos como capa de base de datos para nuestros microservicios internos, ¡y recomendamos de todo corazón Couchbase si necesitas una base de datos NoSQL adecuada!
Este artículo ha sido publicado por Couchbase Programa de escritura comunitaria