No existe una solución clara porque esto depende completamente de su contexto, en particular, según qué dimensiones se supone que su sistema debe escalar y cuáles son sus problemas reales. ¿Es la base de datos realmente su cuello de botella?
Esta respuesta (desafortunadamente bastante larga) se leerá un poco como "¡los microservicios son malos, monolitos para toda la vida!", Pero esa no es mi intención. Mi punto es que los microservicios y las bases de datos distribuidas pueden resolver varios problemas, pero no sin tener algunos problemas propios. Para presentar un argumento sólido para su arquitectura, debe demostrar que estos problemas no se aplican, pueden mitigarse y que esta arquitectura es la mejor opción para las necesidades de su negocio.
Los datos distribuidos son difíciles.
La misma flexibilidad que permite una mejor escala es la otra cara de las garantías más débiles. En particular, los sistemas distribuidos son mucho más difíciles de razonar.
Las actualizaciones atómicas, las transacciones, la coherencia / integridad referencial y la durabilidad son extremadamente valiosas y no se deben renunciar precipitadamente. No tiene mucho sentido tener datos si están incompletos, desactualizados o completamente incorrectos. Cuando tiene ACID como un requisito comercial pero está utilizando tecnología de base de datos que no puede ofrecerla de inmediato (por ejemplo, muchas bases de datos NoSQL o una arquitectura DB por microservicio), su aplicación debe llenar el vacío y proporcionar esas garantías.
Esto no es imposible de hacer, pero es difícil hacerlo bien. Muy engañoso. Especialmente en un entorno distribuido donde hay múltiples escritores para cada base de datos. Esta dificultad se traduce en una alta probabilidad de errores, posiblemente incluyendo datos caídos, datos inconsistentes, etc.
Por ejemplo, considere leer los análisis de Jepsen de sistemas de bases de datos distribuidos bien conocidos , quizás comenzando con el análisis de Cassandra . No entiendo la mitad de ese análisis, pero el TL; DR es que los sistemas distribuidos son tan difíciles que incluso los proyectos líderes de la industria a veces se equivocan, en formas que pueden parecer obvias en retrospectiva.
Los sistemas distribuidos también implican un mayor esfuerzo de desarrollo. Hasta cierto punto, existe una compensación directa entre los costos de desarrollo o la caída de dinero en hardware más robusto.
Ejemplo: referencias colgantes
En la práctica, no debe mirar a la informática sino a los requisitos de su negocio para ver si ACID se puede relajar y cómo. Por ejemplo, muchas relaciones de clave externa pueden no ser tan importantes como parecen. Considere una relación producto - categoría n: m. En un RDBMS podríamos usar una restricción de clave externa para que solo los productos existentes y las categorías existentes puedan ser parte de esa relación. ¿Qué sucede si presentamos servicios separados de productos y categorías, y se elimina un producto o categoría?
En este caso, eso podría no ser un gran problema y podemos escribir nuestra aplicación para que filtre cualquier producto o categoría que ya no exista. ¡Pero hay compensaciones!
Tenga en cuenta que esto puede requerir un nivel de aplicación JOIN
sobre múltiples bases de datos / microservicios, que simplemente mueve el procesamiento del servidor de la base de datos a su aplicación. Esto aumenta la carga total y tiene que mover datos adicionales a través de la red.
Esto puede alterar la paginación. Por ejemplo, solicita los siguientes 25 productos de una categoría y filtra los productos no disponibles de esa respuesta. Ahora su aplicación muestra 23 productos. En teoría, ¡una página con cero productos también sería posible!
Deberá ejecutar ocasionalmente un script que limpie las referencias colgantes, ya sea después de cada cambio relevante o en intervalos regulares. Tenga en cuenta que tales scripts son bastante caros porque tienen que solicitar cada producto / categoría de la base de datos / microservicio de respaldo para ver si todavía existe.
Esto debería ser obvio, pero para mayor claridad: no reutilice las ID. Las ID de estilo de aumento automático pueden o no estar bien. Los GUID o hashes le brindan más flexibilidad, por ejemplo, al poder asignar una ID antes de que el elemento se inserte en una base de datos.
Ejemplo: órdenes concurrentes
Ahora considere una relación producto-orden. ¿Qué sucede con un pedido si un producto se elimina o cambia? Bien, simplemente podemos copiar los datos relevantes del producto en la entrada del pedido para mantenerlos disponibles, intercambiando espacio en disco por simplicidad. Pero, ¿qué sucede si el precio del producto cambia o el producto deja de estar disponible justo antes de que se realice un pedido de ese producto? En un sistema distribuido, los efectos tardan en propagarse y es probable que el pedido se procese con datos obsoletos.
Nuevamente, cómo abordar esto depende de los requisitos de su negocio. Tal vez el pedido desactualizado sea aceptable, y luego puede cancelar el pedido si no se puede cumplir.
Pero tal vez esa no sea una opción, por ejemplo, para configuraciones altamente concurrentes. Considere que 3000 personas se apresuran a comprar entradas para conciertos en los primeros 10 segundos, y supongamos que un cambio en la disponibilidad requerirá 10 ms para propagarse. ¿Cuál es la probabilidad de vender el último boleto a varias personas? Depende de cómo se manejen esas colisiones, pero usando una distribución de Poisson con λ = 3000 / (10s / 10ms) = 3
nosotros tenemos una P(k > 1) = 1 - P(k = 0) - P(k = 1) = 80%
posibilidad de colisión por intervalo de 10 ms. Si es posible vender y luego cancelar la mayoría de sus pedidos sin cometer fraude, puede llevar a una conversación interesante con su departamento legal.
El pragmatismo significa elegir las mejores características.
La buena noticia es que no tiene que pasar a un modelo de base de datos distribuida, de lo contrario no es necesario. Nadie revocará su membresía al Club de microservicios si no realiza microservicios "correctamente", porque no existe tal club, y no hay una forma real de crear microservicios.
El pragmatismo gana cada vez, así que combina y combina varios enfoques a medida que resuelven tu problema. Esto incluso podría significar microservicios con una base de datos centralizada. Realmente, no pase por el dolor de las bases de datos distribuidas si no es necesario.
Puede escalar sin microservicios.
Los microservicios tienen dos beneficios principales:
- El beneficio organizacional de que pueden ser desarrollados e implementados independientemente por equipos separados (lo que a su vez requiere que los servicios ofrezcan una interfaz estable).
- El beneficio operativo de que cada microservicio se puede escalar de forma independiente .
Si no se requiere una escala independiente, los microservicios son mucho menos atractivos.
Un servidor de base de datos ya es un tipo de servicio que puede escalar (algo) de forma independiente, por ejemplo, agregando réplicas de lectura. Usted menciona procedimientos almacenados. Reducirlos podría tener un efecto tan grande que cualquier otra discusión de escalabilidad sea discutible.
Y es perfectamente posible tener un monolito escalable que incluya todos los servicios como bibliotecas. Luego puede escalar iniciando más instancias del monolito, lo que, por supuesto, requiere que cada instancia sea apátrida.
Esto tiende a funcionar bien hasta que el monolito es demasiado grande para ser implementado razonablemente, o si algunos servicios tienen requisitos de recursos especiales, por lo que es posible que desee escalarlos de forma independiente. Los dominios problemáticos que involucran recursos adicionales podrían no involucrar un modelo de datos separado.
¿Tienes un fuerte caso de negocios?
Es consciente de las necesidades comerciales de su organización y, por lo tanto, puede crear un argumento para una arquitectura de base de datos por microservicio, basándose en un análisis:
- que se requiere una cierta escala, y esta arquitectura es el enfoque más rentable para obtener esa escalabilidad, teniendo en cuenta el mayor esfuerzo de desarrollo para dicha configuración y soluciones alternativas; y
- que los requisitos de su negocio permiten que las garantías ACID relevantes se relajen, sin generar varios problemas como los discutidos anteriormente.
Por el contrario, si no puede demostrar esto, en particular si el diseño de la base de datos actual es capaz de soportar una escala suficiente en el futuro (como parecen creer sus colegas), entonces también tiene su respuesta.
También hay un gran componente YAGNI para la escalabilidad. Ante la incertidumbre, es una decisión comercial estratégica para construir escalabilidad ahora (costos totales más bajos, pero implica costos de oportunidad y puede no ser necesario) en lugar de diferir algo de trabajo sobre escalabilidad (costos totales más altos si es necesario, pero tiene una mejor idea de la escala real). Esto no es principalmente una decisión técnica.