Be Software Architecture Wise
Be Wise Apps

Read in English · Lire en français · Auf Deutsch lesen

Sección 7.1 de 7.8 · Intermedio · 24 min de lectura

Propiedad de los datos y base de datos por servicio

Videolección

5 min · narrado en inglés, con subtítulos
Solo escuchar (audio)
Leer la transcripción

El código se divide en servicios con relativa facilidad; los datos, no. En esta lección aprenderás la primera y más importante pregunta sobre los datos: quién es el propietario de cada dato.

Imagina un tablón de anuncios en una cocina, donde cualquiera puede borrar y reescribir los pedidos del día. Con dos cocineros, funciona. Con diez, los pedidos se sobrescriben y nadie sabe quién cambió qué. Una cocina mejor da a cada puesto su propio tablón. La parrilla escribe los pedidos de la parrilla. Los demás puestos los leen, o le piden a la parrilla que los cambie. Eso es la propiedad de los datos: decidir qué parte de un sistema está autorizada a cambiar cada información.

Un sistema de registro es la fuente autorizada de un dato: el lugar cuyo valor prevalece cuando las copias no coinciden. En un banco en línea, el libro mayor central es el sistema de registro de los saldos. El saldo de la app para dispositivos móviles es una copia. El propietario es el único componente que escribe los datos, aplica sus reglas, decide su esquema y los publica para los demás. Una regla útil: el servicio que escribe en una tabla es su propietario.

Este diagrama muestra dos formas de dar sus datos a tres servicios de una plataforma de reparto de comida. A la izquierda, todos comparten una única base de datos. Cada tabla se convierte en una interfaz pública, así que renombrar una columna puede romper servicios que nadie sabía que la leían, y los cambios de esquema requieren un lanzamiento coordinado. Las reglas de negocio también se duplican en cada servicio que escribe en una tabla, y el informe pesado de un servicio ralentiza a todos los demás. A la derecha está la base de datos por servicio. Cada esquema es privado, no hay joins entre bases de datos y los datos cruzan los límites solo mediante llamadas a la API y eventos. Cada propietario puede cambiar su esquema por su cuenta. El precio es que los joins, las transacciones y las comprobaciones de integridad entre servicios deben sustituirse por API, eventos, sagas y pipelines de informes.

La propiedad se complica cuando dos servicios cambian los mismos datos. Esto es la propiedad conjunta, y hay cuatro formas de resolverla. Puedes dividir la tabla, para que cada servicio sea propietario de las columnas que escribe. Puedes mantener un pequeño dominio de datos compartido: sencillo, pero es una base de datos compartida deliberadamente limitada. Puedes delegar: elegir un único propietario y hacer que el otro servicio le envíe solicitudes en lugar de escribir. Esta es la respuesta más habitual para pedidos, pagos y reservas. O puedes fusionar los servicios, la respuesta honesta cuando se dividieron con un grano demasiado fino.

Veamos un ejemplo práctico. Tres servicios escriben todos en la columna de estado de una tabla de pedidos compartida, y los clientes han visto pedidos que pasan de recogido a en preparación. Eso es propiedad conjunta. Gana la última escritura, los mensajes que llegan tarde hacen retroceder el estado y la regla de cancelación se comprueba en dos servicios, de forma distinta. La jugada clave es darse cuenta de que una columna oculta tres hechos: el estado de la comanda de cocina, el estado del trabajo de reparto y el estado que ve el cliente, que combina ambos. La división de la tabla se descartó, porque la regla de cancelación seguiría sin tener un lugar propio. La fusión también se descartó: tres equipos, con cargas muy distintas. Así que Pedidos pasa a ser el único escritor del estado del pedido. El estado solo avanza, así que un mensaje tardío se registra, pero no puede hacerlo retroceder.

Este es el resultado. Los servicios Restaurante y Reparto son propietarios de sus propios hechos y publican eventos como comida lista y recogido. El servicio Pedidos es el único que escribe el estado, y lo almacena en su propia base de datos. Una cancelación desde el restaurante es una solicitud a su API, que puede aceptarla o rechazarla. Todos los demás, como la app del cliente y la herramienta de soporte, leen el estado a través de la API. Cada hecho tiene exactamente un escritor.

Los demás servicios pueden llamar a la API del propietario, que está al día pero los acopla a él, o guardar una copia local alimentada por eventos, que es rápida pero con consistencia eventual. El error habitual es dejar que una copia se convierta en maestro. En cuanto un lector corrige su propia copia, hay dos sistemas de registro, y se irán distanciando. Entre equipos, un contrato de datos establece el esquema, el significado de cada campo, las expectativas de calidad y la frescura, idealmente comprobados de forma automática. Así que, para cada hecho importante, pregúntate: ¿quién es el único escritor?, ¿dónde se aplican sus reglas? y ¿cuán desactualizada puede estar cada copia? Si alguna respuesta es depende, el diseño no está terminado.

La sección completa también trata en detalle los informes que abarcan varios servicios y los contratos de datos. A continuación, en la sección siete punto dos, vemos cómo elegir una base de datos. Nos vemos allí.

Lo que necesitas saber

Por qué la propiedad es la primera pregunta sobre los datos

El Capítulo 6 dividió los sistemas en servicios que se despliegan, se escalan y se cambian de forma independiente. El código se divide con relativa facilidad; los datos, no. Un pedido hace referencia a un cliente, un plato de la carta, un restaurante y un repartidor, y cada equipo quiere leer, y a menudo cambiar, alguna parte de él. Por eso, la pregunta más importante en una arquitectura de datos distribuida no es qué base de datos comprar, sino quién es el propietario de cada dato: qué componente puede cambiarlo, cuál aplica sus reglas y cómo llegan a verlo todos los demás.

La propiedad importa porque los datos sobreviven al código. Los servicios se reescriben cada pocos años; las cuentas de clientes, los libros mayores y los historiales médicos se conservan durante décadas. Equivocarse con la propiedad produce el tipo caro de deuda arquitectónica: dos servicios que no pueden lanzarse por separado porque comparten tablas, un campo de estado que tres equipos sobrescriben por turnos, o un informe mensual que nadie puede reproducir porque las cifras salen de cinco copias de los mismos datos que no coinciden.

Esta sección usa dos ejemplos recurrentes que vuelven a aparecer a lo largo del capítulo: una plataforma de reparto de comida (clientes, restaurantes, repartidores, pedidos) y un banco en línea (clientes, cuentas, pagos, un libro mayor).

Sistema de registro y propiedad de los datos

Un sistema de registro es la fuente autorizada de un dato concreto: el lugar cuyo valor prevalece cuando las copias no coinciden. En el banco, el libro mayor central es el sistema de registro de los saldos de las cuentas; el saldo que se muestra en la app para dispositivos móviles, el que está en la caché del motor de fraude y el de la carga de anoche en el almacén de datos son todos copias. En la plataforma de reparto de comida, el propio servicio de cartas del restaurante es el sistema de registro de los precios, aunque el índice de búsqueda, la caché sin conexión de la app para dispositivos móviles y las líneas de pedido contengan copias de ellos.

La propiedad de los datos convierte esto en una responsabilidad. El componente propietario (y el equipo que hay detrás) es el único que escribe los datos, aplica sus invariantes (reglas que deben cumplirse siempre, como un asiento del libro mayor nunca se edita, solo se revierte), decide su esquema y los publica para los demás a través de una interfaz que controla. La propiedad es una decisión de diseño, no una propiedad de la base de datos: dos servicios pueden estar en el mismo servidor de base de datos y tener aun así una propiedad clara, y dos servicios con bases de datos separadas pueden seguir peleándose por los mismos hechos si el límite entre ellos está mal trazado.

Una regla útil de Software Architecture: The Hard Parts (Neal Ford, Mark Richards, Pramod Sadalage y Zhamak Dehghani, 2021) es que el servicio que escribe en una tabla es su propietario. Compartir la lectura es barato; compartir la escritura no lo es, porque quien escribe debe aplicar las reglas.

La base de datos compartida y por qué acopla los servicios

La forma más sencilla de permitir que varias aplicaciones trabajen con los mismos datos es darles a todas acceso a una única base de datos. Martin Fowler la llamó base de datos de integración (2004): una base de datos que es el punto de integración entre aplicaciones, a diferencia de una base de datos de aplicación, que sirve a una sola aplicación. Parece atractiva: no hay que construir API, los joins funcionan sobre todo y una sola transacción puede actualizar a la vez pedidos y pagos. El veredicto de Fowler, que comparte la mayoría de los arquitectos, es que las bases de datos de integración deben evitarse, porque el acoplamiento que crean es profundo y en gran parte invisible.

Piensa en las formas de acoplamiento que introduce. Acoplamiento de esquema: cada tabla y cada columna es, en la práctica, una API pública. Renombrar orders.state como orders.status rompe cualquier servicio que la lea, y nadie puede estar seguro de cuáles lo hacen, porque las consultas SQL están dispersas por muchas bases de código, informes y hojas de cálculo. Acoplamiento de despliegue: un cambio de esquema tiene que coordinarse entre todos los equipos que tocan la tabla, así que servicios que debían lanzarse de forma independiente se lanzan juntos. Acoplamiento semántico: el esquema debe servir a todos los clientes, así que se vuelve más general y más confuso (Fowler señala que acaba intentando unificar conceptos que pertenecen a contextos delimitados distintos), y las reglas de negocio de una tabla acaban duplicadas, de forma incoherente, en cada servicio que escribe en ella. Acoplamiento en tiempo de ejecución: la consulta lenta de un informe o el proceso por lotes con muchos bloqueos de un servicio degrada a todos los demás, y la base de datos se convierte en un punto único de fallo compartido y en un techo para las conexiones.

Nada de esto es fatal para una sola aplicación o para un monolito modular cuyos módulos respetan las tablas de los demás, ni para la arquitectura basada en servicios de grano grueso, en la que un puñado de servicios de dominio suele compartir una base de datos de forma deliberada. Se convierte en un problema cuando los equipos esperan desplegabilidad independiente pero mantienen las tablas compartidas, que es una vía clásica hacia un monolito distribuido.

Base de datos compartida frente a base de datos por servicio

Izquierda: tres servicios leen y escriben las mismas tablas de una BD compartida. Derecha: cada servicio tiene una BD privada y los demás solo llegan a sus datos mediante su API o sus eventosBD compartida (de integración)Base de datos por servicioPedidosCocinaRepartoUna sola BDpedidos, cartas, repart.tablas comunes a todostodo servicio puede leer ocambiar toda tablacambiar esquema = lanzamiento coordinadoPedidosCocinaRepartoBD pedidosBD cartasBD repartid.llamadas API y eventossolo entre servicioscada esquema es privado;sin joins entre BDel dueño cambia su esquema
Con una base de datos compartida, cada tabla es una interfaz pública; con una base de datos por servicio, cada esquema es privado y los datos cruzan los límites solo mediante API y eventos.

Base de datos por servicio

La alternativa, asociada a los microservicios, es el patrón de base de datos por servicio: los datos persistentes de cada servicio son privados y los demás servicios solo pueden acceder a ellos a través de la API del servicio o de los eventos que publica. El catálogo de patrones de Chris Richardson (microservices.io) señala que esto no tiene por qué significar un servidor distinto por servicio. Hay tres niveles de separación, y la línea importante es la primera.

Tres formas de mantener privados los datos de un servicio

NivelQué está separadoSolidez del límiteUso típico
Tablas privadas por servicioCada servicio tiene su propio conjunto de tablas en una base de datos compartida, con credenciales separadas que solo pueden acceder a esas tablas.La más débil: depende de los permisos y de la disciplina; sigue compartiendo capacidad y fallos.Al principio de una migración; sistemas pequeños; monolitos modulares.
Esquema por servicioCada servicio tiene su propio esquema (espacio de nombres) en un servidor compartido.Propiedad y control de acceso claros; sigue compartiendo el rendimiento y la disponibilidad del servidor.La mayoría de los equipos que empiezan con varios servicios; más barato de operar.
Servidor de base de datos por servicioCada servicio tiene su propia instancia de base de datos, posiblemente de un tipo distinto.La más sólida: escalado, fallos y elección tecnológica separados.Servicios con necesidades muy distintas de carga, forma de los datos o disponibilidad.

Los beneficios son el reflejo de los costos de la base de datos compartida: los propietarios cambian sus esquemas libremente, escalan y ajustan sus almacenes de forma independiente, eligen el tipo de base de datos adecuado y contienen los fallos. Los costos son reales y deben constar en cualquier registro de decisión. Los joins entre servicios desaparecen y deben sustituirse por composición de API o datos replicados. Una sola transacción ACID ya no puede abarcar pedidos y pagos; los cambios entre servicios se convierten en sagas con pasos compensatorios. La integridad referencial entre servicios (todo pedido apunta a un cliente real) ya no la garantizan las claves foráneas. Los informes necesitan un pipeline aparte. Y hay más bases de datos que respaldar, parchear y monitorizar.

The Hard Parts plantea la decisión como un equilibrio de fuerzas. Los desintegradores empujan hacia la división de los datos: el control de cambios (cuántos servicios se rompen cuando cambia una tabla), los límites de conexiones, la escalabilidad, la tolerancia a fallos, el deseo de tener unidades desplegables de forma independiente y la necesidad de distintos tipos de base de datos. Los integradores tiran de los datos para mantenerlos juntos: las relaciones que necesitan integridad referencial y las operaciones que de verdad necesitan una única transacción atómica. Si dos tablas siempre se cambian juntas en una transacción y no tienen vida independiente, eso es una prueba sólida de que pertenecen al mismo propietario.

Cuando varios servicios escriben los mismos datos

Las preguntas sobre la propiedad se vuelven difíciles cuando más de un servicio cambia legítimamente la misma entidad. The Hard Parts distingue tres situaciones. Con la propiedad única, solo un servicio escribe en la tabla y es, sin más, su propietario. Con la propiedad común, la mayoría de los servicios escriben en la misma tabla (un registro de auditoría o un conjunto de parámetros de configuración, por ejemplo); la respuesta habitual es crear un servicio dedicado que sea el propietario de los datos y dar a todos los demás una API, a menudo asíncrona para no ralentizar a quienes escriben. Con la propiedad conjunta, un número pequeño de servicios, normalmente dos, escribe en la misma tabla, por lo general dentro del mismo dominio. El libro ofrece cuatro técnicas para la propiedad conjunta.

Resolver la propiedad conjunta

TécnicaCómo funcionaCompromiso principal
División de la tablaDividir la tabla para que cada servicio sea propietario de las columnas que escribe, en su propia tabla. La fila de orders de la plataforma de reparto de comida se convierte en un pedido cuyo propietario es Pedidos y en una comanda de cocina cuyo propietario es Cocina.Propiedad limpia, pero crear o eliminar la entidad padre tiene que sincronizarse ahora entre servicios, y cualquier vista del conjunto necesita ambas partes.
Dominio de datosMantener la tabla compartida entre los pocos servicios implicados, dentro de un pequeño esquema compartido que controlan conjuntamente.Sencillo y rápido, y las transacciones siguen siendo posibles, pero es una base de datos compartida deliberadamente limitada: los servicios quedan acoplados en los cambios de esquema y el límite entre ellos se debilita.
DelegarElegir un único propietario; el otro servicio le envía solicitudes (llamadas síncronas o comandos asíncronos) en lugar de escribir. El propietario se elige por dominio principal (¿de quién es el concepto?) o por características operativas (¿qué servicio necesita las escrituras más rápidas y con mayor disponibilidad?).Propiedad clara y reglas en un solo lugar, a costa de un salto de red adicional, un nuevo modo de fallo y posiblemente consistencia eventual para el servicio que delega.
Consolidación de serviciosFusionar en un solo servicio los servicios que comparten los datos.Elimina el problema y recupera las transacciones locales, pero crea un servicio más grande, con despliegue, escalado y aislamiento de fallos de grano más grueso.

Ninguna técnica es gratuita, y la adecuada depende de con qué frecuencia cambian los datos, de cuán estrictas son sus reglas y de cuán independientes necesitan ser los equipos. En la práctica, delegar es la respuesta más habitual para las entidades de negocio con un ciclo de vida (pedidos, pagos, reservas), la división de la tabla funciona bien cuando las columnas escritas conjuntamente son en realidad hechos distintos que casualmente se almacenaban juntos, y la consolidación es la respuesta honesta cuando los dos servicios se dividieron con un grano demasiado fino desde el principio.

Leer datos de los que no eres propietario

Una vez resuelta la propiedad, todos los demás servicios siguen necesitando leer los datos. La pantalla de cocina necesita las notas de entrega del cliente; el motor de fraude necesita los pagos recientes de la cuenta. Hay cuatro grandes opciones, y cada una intercambia frescura por acoplamiento. Ten en cuenta que los diseños dirigidos por eventos, tratados en el Capítulo 6, proporcionan la tercera y la cuarta.

Formas de leer los datos de otro servicio

OpciónCómo funcionaFrescuraAcoplamiento y costo
Llamada síncronaConsultar la API del propietario en el momento en que se necesitan los datos.Actuales, en el momento de la llamada.Acoplamiento en tiempo de ejecución: si el propietario está lento o caído, también lo está quien llama; las latencias se suman a lo largo de una cadena.
Replicación de esquemas de columnasCopiar las pocas columnas necesarias (por ejemplo, el nombre y la dirección del restaurante) en la base de datos propia del lector, mantenidas al día mediante eventos o captura de datos de cambios.Consistencia eventual: desactualizados según el retardo de replicación.Lecturas y joins locales rápidos; el lector debe gestionar las actualizaciones tardías o perdidas y no debe escribir nunca en la copia.
Caché replicadaUn grid de datos en memoria (como Hazelcast o Apache Ignite) mantiene una copia de los datos del propietario en cada servicio consumidor, sincronizada por el grid.Casi en tiempo real.Lecturas muy rápidas; costo de memoria, carga al arrancar y complejidad operativa del grid.
Eventos (transferencia de estado transportada por eventos)El propietario publica eventos que transportan los datos modificados; los lectores guardan lo que necesiten.Consistencia eventual.Acoplamiento temporal débil; los lectores deben hacer frente a los duplicados, al orden y a la evolución de esquemas.

Fowler llama a la cuarta opción transferencia de estado transportada por eventos: eventos como MenuItemPriceChanged transportan los nuevos valores, así que los consumidores no necesitan volver a llamar. Un mecanismo relacionado, la captura de datos de cambios (CDC), lee el log de la base de datos del propietario y convierte cada cambio confirmado en un evento, lo que evita el problema de la escritura dual (escribir en la base de datos y publicar un evento por separado, de modo que una operación puede tener éxito mientras la otra falla). La bandeja de salida transaccional (transactional outbox), que resuelve el mismo problema desde dentro de la aplicación, se trata junto con las sagas.

Informes que abarcan varios servicios

La base de datos por servicio complica una tarea antigua: el informe transversal. Ingresos por restaurante y por semana, descontando los reembolsos, desglosados por tipo de repartidor necesita pedidos, pagos, restaurantes y entregas. Generarlo llamando a cuatro API página a página es lento y carga a los servicios operativos con el trabajo de los informes. Consultar directamente sus bases de datos reintroduce por la puerta de atrás el acoplamiento de la base de datos compartida.

La respuesta habitual es separar los informes de las operaciones. Fowler describió una base de datos de informes: un almacén separado, con una forma pensada para las consultas y alimentado desde los sistemas operativos, que los usuarios de informes pueden leer libremente. Hoy suele ser un almacén de datos o un lakehouse alimentado por CDC o por eventos, que se trata en analítica y streaming. Para vistas pequeñas y casi en tiempo real dentro del producto (el panel de los pedidos del día de un restaurante), un servicio puede construir su propio modelo de lectura a partir de eventos, la idea que hay detrás de CQRS. En cualquier caso, los pipelines que alimentan los informes dependen de las estructuras de datos de los propietarios, y por eso necesitan contratos.

Contratos de datos

Un contrato de datos es un acuerdo explícito y versionado entre el propietario de un conjunto de datos y sus consumidores. Establece el esquema (campos, tipos, cuáles pueden ser nulos), el significado de cada campo (¿amount está en peniques o en libras, con IVA o sin él?), las expectativas de calidad (ningún identificador de pedido duplicado, como máximo un 0.1% de filas sin restaurante), los niveles de servicio (cuán frescos son los datos, cuánto tiempo se conservan), quién es su propietario y cómo se anuncian los cambios. Aplica la idea de un contrato de API a los datos que circulan entre equipos mediante eventos, flujos de CDC y tablas del almacén de datos.

Los contratos son más útiles cuando son legibles por máquina y se comprueban automáticamente: un pipeline que rechaza un cambio de esquema que rompería a los consumidores registrados, o una prueba que falla cuando se incumple una regla de calidad. El Open Data Contract Standard (ODCS), mantenido por el proyecto Bitol bajo la Linux Foundation AI & Data, define un formato YAML que abarca el esquema, las reglas de calidad, los niveles de servicio, los roles y los canales de soporte. Los contratos de datos no son gratuitos: alguien tiene que escribirlos y mantenerlos, y los contratos demasiado estrictos frenan el cambio. The Hard Parts contrapone los contratos estrictos (precisos, verificables, con un acoplamiento fuerte) a los flexibles (más fáciles de hacer evolucionar, pero que necesitan más pruebas), y propone como término medio los contratos dirigidos por el consumidor, en los que los consumidores indican lo que realmente usan. Cómo cambiar un esquema sin romper a los consumidores es el tema de evolución de esquemas.

Ejemplo práctico

Ejemplo práctico: ¿quién es el propietario del estado del pedido en la plataforma de reparto de comida?

La plataforma tiene tres servicios a los que les importa el progreso de un pedido: Pedidos (recibe los pedidos y gestiona su pago), Restaurante (la tableta de la cocina: acepta pedidos, marca la comida como lista) y Reparto (asigna repartidores, sigue la recogida y la entrega). Hoy los tres escriben en la columna status de una tabla orders compartida. Los clientes han visto pedidos que pasan de Recogido a En preparación, y nadie sabe decir dónde están las reglas de cancelación.

DiagnosticarPropiedad conjunta de una columna por parte de tres escritores. Cada uno escribe lo que sabe, gana la última escritura y los mensajes que llegan tarde hacen retroceder el estado. La regla un pedido solo puede cancelarse antes de que la cocina empiece se comprueba en dos servicios, de forma distinta.
Separar los hechosEn realidad hay tres hechos: el estado de la comanda de cocina (cuyo propietario es Restaurante), el estado del trabajo de reparto (cuyo propietario es Reparto) y el estado del pedido que ve el cliente, que combina ambos y contiene las reglas de negocio (cancelación, reembolsos, compensación).
Opción: división de la tablaDar a cada servicio su propia columna de estado y dejar que los lectores los combinen. Descartada: cada lector (la app, la herramienta de soporte, las notificaciones) volvería a implementar la combinación, y la regla de cancelación seguiría sin tener un lugar propio.
Opción: consolidación de serviciosFusionar los tres en un solo servicio. Descartada: tres equipos, cargas muy distintas (las actualizaciones de ubicación de los repartidores llegan cada pocos segundos) y ciclos de lanzamiento diferentes.
Decisión: delegarPedidos es el único escritor de order_status. Restaurante y Reparto son propietarios de sus propios hechos y publican eventos (OrderAccepted, FoodReady, PickedUp, Delivered). Pedidos los consume y aplica una máquina de estados. Una cancelación desde la tableta del restaurante es una solicitud a la API de Pedidos, que la acepta o la rechaza.
Máquina de estadosPLACED, ACCEPTED, PREPARING, READY, PICKED_UP, DELIVERED, con CANCELLED permitido solo desde PLACED o ACCEPTED. Las transiciones solo avanzan, así que un FoodReady tardío que llega después de PickedUp se registra pero no cambia el estado; los duplicados se ignoran.
ConsecuenciasUn solo lugar para las reglas; ningún salto hacia atrás; cada equipo lanza de forma independiente. Costos: el estado va por detrás de la cocina según el retardo de los eventos (normalmente muy por debajo de un segundo), Pedidos debe estar disponible para aceptar cancelaciones y los eventos se convierten en un contrato que debe versionarse.

La jugada clave no fue elegir una técnica de la tabla, sino darse cuenta de que una columna ocultaba tres hechos distintos con tres propietarios naturales.

Deja constancia de la decisión en un registro de decisiones de arquitectura, incluidas las opciones descartadas; el próximo equipo que pregunte ¿por qué no podemos actualizar el estado sin más desde la app del repartidor? lo necesitará.

El estado del pedido después de la decisión

Los servicios Restaurante y Reparto son propietarios de sus propios hechos y publican eventos; el servicio Pedidos los consume y es el único que escribe el estado del pedido, que los clientes y el soporte leen a través de su APIServicio Restaurantedueño de la comandaaceptada, listaServicio Repartodueño trab. repartoasignado, recogidoOrderAccepted,FoodReadyPickedUp,Deliveredcancelación (API)Serv. Pedidossolo él escribeorder_status(máq. de estados)OrderCancelledBD pedidosApp clientelee el estado vía APIHerr. soportelee el estado vía APICada hecho tiene un solo escritor; los demás leen o solicitan
Cada hecho tiene un solo escritor: Restaurante y Reparto publican aquello de lo que son propietarios, y solo el servicio Pedidos convierte esos eventos en el estado que ve el cliente.

Errores comunes

Dividir los servicios pero mantener las tablas compartidas. Los equipos cargan con el costo operativo de la distribución sin la independencia que se suponía que iba a comprar. Si los servicios no pueden desplegarse sin coordinar un cambio de esquema, no son independientes. Servicios de entidad. Un CustomerService que no es más que crear, leer, actualizar y eliminar sobre una tabla, y al que llaman todos los demás servicios, es una base de datos compartida con latencia adicional; la propiedad debe seguir a las capacidades de negocio y sus reglas, no a los sustantivos. Copias que se convierten discretamente en maestros. Consulta la advertencia anterior. Dejar los informes para el final. El primer informe financiero tras la división suele revelar que nadie planificó cómo volver a reunir los datos. Tratar la propiedad como algo puramente técnico. La propiedad también es organizativa: alguien debe responder de la calidad de los datos y, según la ley de Conway, los límites de datos que atraviesan los límites entre equipos tienden a no durar.

Una buena prueba para cualquier diseño de datos es hacerse, para cada hecho importante, tres preguntas: ¿quién es el único escritor?, ¿dónde se aplican sus reglas? y ¿cuán desactualizada puede estar cada copia? Si alguna respuesta es depende o varios servicios, el diseño no está terminado.

Comprueba lo que has entendido

Dos servicios actualizan cada uno la columna status de la misma tabla. ¿Qué tipo de propiedad es esta? Nombra dos formas de resolverla.

Propiedad conjunta. Puede resolverse dividiendo la tabla, delegando las escrituras en un único propietario, manteniendo un pequeño dominio de datos compartido o consolidando los servicios.

¿Por qué una base de datos compartida socava el despliegue independiente?

Cada tabla es, en la práctica, una interfaz pública, así que un cambio de esquema debe coordinarse con todos los servicios que la leen o escriben, lo que obliga a lanzamientos conjuntos.

¿Cuál es la diferencia entre la replicación de esquemas de columnas y una llamada síncrona a la hora de leer los datos de otro servicio?

La replicación mantiene una copia local con consistencia eventual que es rápida y está disponible aunque el propietario esté caído; una llamada síncrona devuelve datos actuales, pero acopla la disponibilidad y la latencia de quien llama a las del propietario.

¿Qué añade un contrato de datos además de un esquema?

El significado de los campos, las expectativas de calidad, los niveles de frescura y de conservación, la propiedad y cómo se anuncian y versionan los cambios.

Siguiente · 7.2Elegir una base de datosEn qué es buena y en qué es mala cada familia de bases de datos, desde las relacionales hasta las vectoriales y el SQL distribuido, y cómo elegir según la forma de los datos, los patrones de acceso, la consistencia, la escala, la operación y las habilidades del equipo.Continuar →

Fuentes y lecturas recomendadas

¿Tienes una pregunta sobre esta sección? ArchitectBot, el asistente de estudio con IA del curso, responde primero a partir del curso.

Pregunta: “Estamos dividiendo nuestro monolito en servicios, pero todos siguen usando la misma tabla de pedidos. ¿Cómo debemos decidir qué servicio es el propietario de qué datos?”