Comentando con unos compañeros, nos hemos encontrado con una casuística interesante en la que el uso de CDC podría suponer una buena solución más allá del uso básico de esta tecnología.

La situación es la siguiente:

Nos encontramos con un acceso muy frecuente a un origen de datos (una base de datos), mayoritariamente de tipo lectura. Los datos se obtienen a partir de la unión de la información de varias tablas para proporcionar el dato enriquecido y evitar consecuentes llamadas.

Se busca optimizar la lectura de esta información de forma que se pueda reducir la carga que debe soportar el origen de datos.

Vamos a poner un ejemplo que nos permita contextualizar mejor la información: pensemos, por lo tanto, en una aplicación tipo e-commerce en la que debemos mostrar al usuario el ‘dashboard’ inicial con la información más relevante tras haber hecho el login. De forma simplificada, podríamos tener algo así:

  • Usuarios
  • Productos
  • Mensajes
  • Ventas

Cuando un usuario se conecta, este ‘dashboard’ debería mostrar información sobre las ventas más relevantes de sus productos (con distinta información al respecto), preguntas, comentarios y valoraciones que los usuarios hayan podido realizar.

Para poder obtener esta información, como comentábamos anteriormente, es necesario unificar la información de distintas tablas. Actualmente, se hace vía código a través de un servicio que agrega la información:

Caché siempre actualizada  con cdc

Los datos deben estar vivos, es decir, cada vez que se produce una modificación en los datos, la información a mostrar en el dashboard debe actualizarse.

Vemos que hemos implementado de forma natural el patrón CQRS, en el que los datos se almacenarán siguiendo un modelo (directamente sobre ventas o mensajes) y se recuperan siguiendo otro distinto de forma agregada.

Vamos a dar por hecho que las ‘obviedades’ se han implementado de forma adecuada, es decir, las tablas tienen índices adecuados, están particionadas correctamente, etc. pero que, aun así, se busca optimizar dado el alto volumen de trabajo que la base de datos debe soportar.

Soluciones tradicionales a nuestro problema

Vistas materializadas

Como en este caso de uso se realizan principalmente lecturas frente a escrituras, una de las opciones más habituales es la de producir un dato desnormalizado ya listo para ser consumido, de forma que penalizamos la escritura para favorecer la lectura.

Esta aproximación se puede conseguir fácilmente con, por ejemplo, una vista materializada.

Operaciones de actualización o consulta de datos.

Como vemos, dotamos al concepto ‘dashboard’ de entidad propia, y existe un almacenamiento específico para obtener el dato listo para ser consumido: hemos movido el concepto de CQRS del código a la base de datos.

Esta primera aproximación alivia el procesamiento en base de datos (para la lectura), pero no soluciona el problema del número de peticiones que va a recibir.

Caché

El uso de una caché nos puede solucionar fácilmente el problema de las peticiones a BD. Además, puede ser incluso complementario al uso de las vistas materializadas.

Por un lado, podríamos aplicar la caché para simplemente recoger la información en crudo y con ella obtener el dato enriquecido que queremos proporcionar.

El uso de una caché nos puede solucionar fácilmente el problema de las peticiones a BD

Por otro lado, podemos hacer uso de la caché para almacenar directamente la información de la vista materializada, lo que podría incluso aliviar la carga de ‘computación’ en el backend para generar ese dato enriquecido.

Uso de la caché para almacenar directamente la información de la vista materializada,

Uno u otro dependerá de la situación. El primero da una solución más general, de la que se podrán incluso beneficiar otros casos de uso, mientras que el segundo es una solución más directa y a medida para la problemática actual.

Problemas de estas aproximaciones

Estas aproximaciones no están exentas de efectos ‘laterales’. Respecto de las vistas materializadas:

  • Las vistas materializadas tienen unas capacidades limitadas a la hora de realizar transformaciones, desnormalizaciones o enriquecimientos. En muchos casos, sus capacidades pueden ser suficientes, pero es necesario tenerlo en cuenta. La peor situación la encontramos cuando esta alternativa es suficiente inicialmente, pero a medida que los requisitos evolucionan deja de serlo, lo que nos obliga a modificar la solución.
  • Con las vistas materializadas estamos metiendo ‘lógica’ de alguna forma en nuestro motor de base de datos, más difícil de versionar e incluso evolucionar.
  • Aunque hemos indicado como premisa que las escrituras serían limitadas, en algunos casos ciertas transformaciones o enriquecimientos pueden resultar pesadas para el motor de base datos.

Respecto de la caché:

  • Todo sistema de caché tiene un problema intrínseco en su uso: los datos pueden no estar actualizados cuando los recojamos. Existen múltiples políticas de invalidación de los datos cuando hablamos de cachés, la más frecuente es simplemente por tiempo. Es decir, una vez se almacena un dato, ese dato se considera válido durante un tiempo determinado tras el cual se marca como inválido y, por lo tanto, es necesario recoger la información de la fuente original. Establecer un tiempo de invalidación muy reducido implicará muchas consultas al origen de los datos. Un tiempo muy alto incrementará el riesgo de recoger un dato ‘antiguo’, no actualizado.

Aplicando CDC para la invalidación de la caché

Como sabemos, CDC (a través de la lectura de los logs transaccionales) nos proporciona un mecanismo reactivo para enterarnos de qué ocurre en la base de datos con un impacto realmente bajo, así que puede ser un buen mecanismo para la invalidación o la actualización de la caché, dependiendo de nuestro caso de uso.

El gran Gunnar Morling explica en una de sus charlas este proceso:

Caché siempre actualizada cdc 5

Este esquema se puede aplicar fácilmente a cualquier de las situaciones que indicamos anteriormente, tanto para capturar los datos originales como para el dato cocinado.

Ventajas de esta aproximación

La forma de reaccionar frente a los cambios nos proporciona mucha flexibilidad, ya que podemos implementarlo fácilmente con piezas adicionales. Por lo tanto:

  • Nos permite realizar la transformación fuera del entorno de la base de datos e incluso fuera del entorno habitual del operacional productivo, si fuera necesario.
  • La lógica de las transformaciones está en código, versionado y con facilidad de evolucionar.
  • Permite una invalidación / actualización reactiva, cercana al tiempo real, reduciendo (que no eliminando completamente) la problemática del tiempo de actualización de la caché.

Esta solución es también válida si tratamos con arquitecturas más modernas (donde tenemos los distintos servicios distribuidos en vez de una única pieza monolítica que trabaja sobre un único esquema de datos) al permitir externalizar la fase de transformación.

Inconvenientes de esta aproximación

El principal inconveniente que podemos encontrar en esta aproximación es el incremento de la complejidad de nuestra arquitectura. Estamos metiendo piezas adicionales que debemos operar, gestionar… y, por supuesto, añadimos nueva tecnología sobre la que hace falta tener un expertise y que es necesario incorporar dentro del ciclo de vida de los productos.

Esta solución requiere de tecnología adicional al propio producto como hemos visto (en este caso, un broker de mensajería o algún tipo de sistema de asincronía).

Adicionalmente, la invalidación / actualización de la caché siempre va a tener una latencia (por mucho que la consideremos mínima, sigue existiendo). El caso de uso será el que nos indique si este retraso es aceptable o no.

Conclusión

En este post hemos visto otro caso de uso alternativo de la tecnología CDC que nos puede ayudar en este tipo de situaciones, que si bien pueden parecer muy específicas, suelen ser mucho más frecuentes de lo que pensamos.

Este tipo de soluciones, en contextos en los que ya se está trabajando con infraestructuras que proporcionen mecanismos de tiempo real, son relativamente rápidas de implementar y permiten disponer de la información no solo para el caso de uso principal, lo que habilita la creación de nuevo negocio.

¡Os animo a que le deis una vuelta!

Cuéntanos qué te parece.

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.