Cuando los desarrolladores oímos el término dispersión de datos, puede sonar un poco como un término de negocios como TCO, ROI y similares. Todos estos términos tienen una realidad para los desarrolladores, fuera del ámbito de los analistas y gestores. Así que hoy quiero hablarte de la realidad de la dispersión de datos para los desarrolladores. Cómo afecta a nuestro trabajo.
La dispersión de datos se puede resumir en que tenemos datos, una cantidad enorme, almacenados en muchos almacenes de datos diferentes. Y encima, nosotros como desarrolladores tenemos que hacer que esos almacenes de datos interactúen entre sí. Y claro, cuantos más, mejor, ¿no 😬?
Suele asociarse a mayores costes financieros en:
-
- Infraestructura
- Licencias
- Integración
- Formación
- Operativo
- Gastos de apoyo
Las plataformas separadas con múltiples interfaces te darán dolores de cabeza por:
-
- Implantación y gestión independientes
- Diferentes modelos de datos e interfaces de programación
- Integración entre varios productos
- Tickets de soporte con diferentes proveedores
Y tenemos que dedicar más tiempo, esfuerzos y costes a causa de:
-
- Licencia y acuerdo
- Formación para desarrolladores y operaciones
- Ayuda
- Construir API o conector a base de datos
- Adquirir infraestructura
Resulta un poco sombrío cuando se mira así, pero es un reto cotidiano para muchas empresas. Y no solo con las diferentes cargas de trabajo de datos, también ocurre con las aplicaciones en la nube.
Veamos un ejemplo concreto. He creado una aplicación que utiliza CRUD de una base de datos de documentos, Caché de un almacén de caché, y búsqueda de un motor de búsqueda de texto completo. (Fuente GitHub)
Echando un vistazo a este esquema, básicamente puedes contar cada flecha que ves como una interacción entre diferentes sistemas que los desarrolladores tienen que pensar y codificar.
Aquí estamos sincronizando automáticamente las bases de datos de Caché y Búsqueda utilizando streaming de eventos. Esto supone 8 interacciones y 4 almacenes de datos que aprender y gestionar. Como necesitas asegurarte de que cada almacén está conectado con el servicio de streaming, y que recibe las actualizaciones correctas, necesitas gestionar el servicio de streaming, la búsqueda, la caché y el almacén de datos. También necesitas integrar la caché con tu servicio CRUD (idealmente con los otros servicios, pero mantengámoslo simple). En resumen: hay mucho que hacer.
Podemos limitar esas interacciones deshaciéndonos de los servicios de streaming y asegurándonos de que otros servicios se actualizan manualmente. Esto es una licencia menos, algo que operar, algo que aprender, algo que integrar. Aún no es lo ideal, pero podría ser así:
Es un poco más sencillo, sólo 6 interacciones y 3 almacenes de datos en lugar de 8 y 4. Pero sigue habiendo muchas interacciones y parte de la integración de streaming tiene que hacerse manualmente. Mientras que antes podríamos haber aprendido y utilizado los conectores existentes entre los servicios existentes. Echemos un vistazo rápido al código de ejemplo Java/Spring Boot escrito para esto.
Existen 4 interfaces que representan lo que los desarrolladores pueden hacer con los almacenes de datos. CRUD, Caché, Consulta y Búsqueda.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
público interfaz CRUD { StoredFileDocument leer(Cadena id); void crear(Cadena id, StoredFileDocument doc); void actualización(Cadena id, StoredFileDocument doc); void upsert(Cadena id, StoredFileDocument doc); void borrar(Cadena id); } público interfaz Caché { void writeInCache(StoredFileDocument doc); StoredFileDocument readFromCache(Cadena id); void toque(Cadena id); void desalojar(Cadena id); } público interfaz Consulta { Lista<Mapa<Cadena, Objeto>> consulta(Cadena whereClause); Lista<Mapa<Cadena, Objeto>> findAll(); } público interfaz Buscar en { Lista<Mapa<Cadena, Objeto>> busque en(Cadena plazo); void índice(StoredFileDocument doc); void borrar(Cadena id); } |
No vamos a mostrar todo el código en este post, sino sólo algunas de las piezas interesantes.
Estamos en una configuración en la que el servicio CRUD tiene enlaces con los servicios Search y Cache. Veamos como quedaría con una versión simplificada. Tenemos que importar los servicios Cache y Search ya que son necesarios. A partir de ahí, todos los métodos se ven afectados por ellos. Read necesita primero consultar la caché, actualizar la última vez que el objeto ha sido encontrado en la caché u obtenerlo de la base de datos e insertarlo en la caché. A continuación, los métodos de creación, actualización y eliminación afectan a la caché y a la búsqueda, ya que los datos recién creados, actualizados o eliminados deben propagarse a la caché o a los índices del almacén de datos de búsqueda.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
@Servicio público clase MongoCRUD implementa CRUD { privado MongoCollection<StoredFileDocument> colección; privado Caché caché; privado Buscar en busque en; público MongoCRUD(MongoCollection<StoredFileDocument> colección, Caché caché, Buscar en busque en) { este.colección = colección; este.caché = caché; este.busque en = busque en; } @Override público StoredFileDocument leer(Cadena id) { StoredFileDocument doc = caché.readFromCache(id); si (doc == null) { Sistema.fuera.println(id); doc = colección.encontrar(eq("fileId", id)).primero(); caché.writeInCache(doc); } si no { caché.toque(id); } devolver doc; } @Override público void crear(Cadena id, StoredFileDocument doc) { doc.setFileId(id); colección.insertarUno(doc); caché.writeInCache(doc); busque en.índice(doc); } @Override público void actualización(Cadena id, StoredFileDocument doc) { colección.findOneAndReplace(eq("fileId", id), doc); caché.toque(id); busque en.índice(doc); } @Override público void upsert(Cadena id, StoredFileDocument doc) { FindOneAndReplaceOptions opciones = nuevo FindOneAndReplaceOptions().upsert(verdadero); colección.findOneAndReplace(eq("fileId", id), doc, opciones); caché.toque(id); busque en.índice(doc); } @Override público void borrar(Cadena id) { colección.deleteOne(eq("fileId", id)); caché.desalojar(id); busque en.borrar(id); } } |
Con Couchbase esto sería más parecido a algo como esto:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
@Servicio Perfil("couchbase") público clase CouchbaseCRUD implementa CRUD { privado Colección colección; público CouchbaseCRUD(Colección colección) { este.colección = colección; } @Override público StoredFileDocument leer(Cadena id) { ObtenerResultado res = colección.consiga(id); devolver res.contentAs(StoredFileDocument.clase); } @Override público void crear(Cadena id, StoredFileDocument doc) { MutationResult res = colección.insertar(id, doc); } @Override público void actualización(Cadena id, StoredFileDocument doc) { MutationResult res = colección.sustituir(id, doc); } @Override público void upsert(Cadena id, StoredFileDocument doc) { MutationResult res = colección.upsert(id, doc); } @Override público void borrar(Cadena id) { MutationResult res = colección.eliminar(id); } } |
La razón por la que no necesitamos una dependencia al servicio de Caché y Búsqueda es porque Couchbase ya integra una caché y un motor de búsqueda. No hay necesidad de implementar la interfaz de Cache, y no hay necesidad de implementar el método de borrado e indexado de la interfaz de búsqueda. Está todo automatizado e integrado.
Normalmente, cuando se lo explico a alguien, surge una conversación sobre lo malo que debe ser, porque hay que hacer concesiones para poder hacer todas las cosas. No todas las plataformas de datos, multimodelo, multicarga de trabajo, o como quiera llamárselas, se crean igual, o al menos no con la misma arquitectura en mente.
Couchbase puede verse como varias bases de datos diferentes, todas responsables de diferentes cargas de trabajo y todas integradas entre sí a través de su servicio interno de streaming. De esta forma, cada parte de Couchbase se mantiene actualizada automáticamente y cada parte puede especializarse en su propia carga de trabajo de datos. Al final, tienes 3 interacciones y 1 almacén de datos.
Esto ya es bastante bueno, pero tenemos una cosa más. Nuestros servicios están integrados en nuestro lenguaje de consulta SQL++. Tomemos un ejemplo. Usted tiene un CMS que contiene un árbol de documentos, con varios permisos en cada documento, y esos permisos pueden ser heredados por los documentos hijos en los que desea ejecutar una búsqueda como un usuario conectado con un conjunto específico de permisos. Si está utilizando un motor de búsqueda externo, lo que suele suceder es:
-
- Ejecutar una consulta al motor de búsqueda
- Recopilar los identificadores de los documentos devueltos, ya que no todo el contenido de los documentos está indexado.
- Ejecutar una consulta para obtener los documentos completos
- Si su servicio de consulta no admite JOIN, ejecute otra consulta para obtener permisos heredados y filtrar los documentos.
Si quisiéramos complicar más las cosas (y quizá también hacerlas más reales) podríamos añadir una lógica de caché personalizada a cada paso. Pero ya es suficientemente complicado.
Couchbase puede hacerlo todo en un solo paso. En una consulta SQL++ podemos buscar, seleccionar los campos que queramos, y hacer JOIN en otros documentos para ordenar los permisos. Así de sencillo. Como Couchbase es una plataforma de datos bien integrada, su lenguaje de consulta te permite aprovechar todos sus poderes. Si te interesa, los detalles pueden venir en otro post.
Conclusión
¿Qué hemos aprendido hoy? Utilizar una Plataforma de Datos bien diseñada puede ahorrarte mucho tiempo, dinero, esfuerzo y quebraderos de cabeza. Porque, al final, tienes menos cosas en las que pensar, menos código que escribir, lo que significa menos código que mantener, y una capacidad más rápida para enviar a producción. Por suerte, también simplifica y ahorra en aspectos como licencias, formación, cumplimiento y todas esas cosas que preocupan a los gestores, analistas, su jefe y el jefe de su jefe.
- Vea mi charla con RedMonk: ¿Qué es la dispersión de datos? Cómo aprovechar una plataforma para gestionarlos
- Echa un vistazo al código de mi ejemplo de dispersión de datos
- Más información Servicios Couchbase están diseñados para que el desarrollo sea fluido y sencillo.
- Pruebe el Couchbase Capella DBaaS para ponerlo a prueba


