---
marp: true
theme: uncover
paginate: false
size: 16:9
backgroundColor: #f4f5f7
color: #1f2933
style: |
section {
font-size: 1.8em;
}
h1, h2, h3 {
color: #0f172a;
}
/* Texto secundario */
p, li {
color: #1f2933;
}
/* Cajas destacadas */
.box {
border: 3px solid #2563eb;
padding: 1em;
border-radius: 12px;
background-color: #e0e7ff;
color: #1e293b;
}
.box-compact{
font-size: 85% !important;
line-height: 1.5;
}
.box-supercompact{
font-size: 65% !important;
line-height: 1.2;
}
.left{
text-align: left;
}
.columns {
display: flex;
gap: 1em;
justify-content: center;
align-items: stretch;
}
.box.warning {
border-color: #ffeeba;
background-color: #fff3cd;
}
.box.danger {
border-color: #f5c6cb;
background-color: #f8d7da;
}
.box.success {
border-color: #c3e6cb;
background-color: #d4edda;
}
/* Alineación */
.left {
text-align: left;
}
/* Código */
pre, code {
background-color: #e5e7eb;
color: #111827;
}
.w-30 { width: 30%; }
.w-40 { width: 40%; }
.w-50 { width: 50%; }
.w-60 { width: 60%; }
.w-70 { width: 70%; }
.w-80 { width: 80%; }
.center {
margin-left: auto;
margin-right: auto;
}
---
# Spring Data:
### Persistencia en Sistemas Políglotas y Reactivos
##### Daniel García Costa
###### 2026
---
## ¿Qué es una arquitectura políglota?
- Uso de **múltiples tecnologías de almacenamiento** en un mismo sistema
- Cada tecnología se utiliza según **sus fortalezas**
- No existe una única base de datos que resuelva todos los problemas
Hay que usar la tecnología adecuada para cada situación
---
### Relacionales (SQL)
| Tipo | Características principales | Casos de uso | Ejemplos |
|-------------------------|--------------------------------------------------------------|--------------------------------------|--------------------------|
| Relacional clásico | ACID, modelo tabular, integridad referencial | Aplicaciones empresariales, CRUD | PostgreSQL, MySQL |
| OLTP | Optimizado para muchas transacciones pequeñas | Sistemas operacionales (apps, APIs) | PostgreSQL, Oracle |
| OLAP / Data Warehouse| Optimizado para consultas analíticas complejas | BI, reporting, análisis de datos | Snowflake, Redshift |
| HTAP (híbrido) | Mezcla OLTP + OLAP en tiempo real | Sistemas con analítica en vivo | TiDB, Azure SQL HTAP |
| Distribuido | Escalado horizontal, replicación, particionado | Sistemas globales y escalables | CockroachDB, YugabyteDB |
---
### No Relacionales (NoSQL)
| Tipo | Características principales | Casos de uso | Ejemplos |
|--------------------|-----------------------------------------------------|---------------------------------------|---------------------|
| Documentales | Datos JSON/BSON, esquema flexible | APIs, datos semiestructurados | MongoDB, CouchDB |
| Clave-Valor | Acceso ultrarrápido por clave | Cache, sesiones, estado temporal | Redis, DynamoDB |
| Grafos | Relaciones complejas entre nodos | Redes sociales, recomendaciones | Neo4j |
| Columnar (Wide) | Columnas distribuidas, gran escalabilidad | Big Data, logs, eventos masivos | Cassandra, HBase |
| Búsqueda | Indexación y búsqueda full‑text | Buscadores, analítica textual | Elasticsearch |
| Series temporales| Optimizadas para datos con timestamp | IoT, métricas, monitoring | InfluxDB, Timescale |
| Multi‑modelo | Soportan varios modelos en un mismo motor | Sistemas híbridos complejos | ArangoDB, Cosmos DB |
---
#### No hay una única solución óptima
Cada tipo resuelve un problema distinto
Por eso las arquitecturas modernas son **políglotas**
---
#### Complejidad
- Uso de múltiples tecnologías == mayor complejidad global
- Diferentes modelos de datos y APIs
- Necesidad de orquestar varios sistemas
#### Puntos de fallo
- Cada tecnología añade:
- configuración propia
- características específicas de despliegue
- monitorización
---
## Problemas más comunes
### Consistencia de datos
- No hay transacciones distribuidas sencillas
- Posibles inconsistencias:
- estado actualizado en un sistema pero no persistido en otro
- fallos en mitad del proceso
**Necesario diseñar tolerancia a fallos**
---
## Sincronización entre sistemas
- ¿Cuándo mover los datos?
- en tiempo real
- mediante eventos
- mediante schedulers
**El diseño del flujo de datos es crítico**
---
### Transformación de datos
- Cada sistema tiene su propio modelo:
- entidades (Java)
- DTOs
- documentos (Mongo)
- Key/Value (Redis)
- ...
### Dificultad de debugging
- Errores distribuidos entre servicios
- Fallos difíciles de rastrear:
- llamadas remotas
- errores de serialización
- inconsistencias de datos
---
## Conclusión
**Mayor flexibilidad implica mayor responsabilidad**
---
## Caso práctico: Plataforma de Subastas
### Problema
Diseñar un sistema capaz de:
- Gestionar subastas en tiempo real
- Registrar pujas concurrentes
- Mantener un histórico completo
- Escalar correctamente ante múltiples usuarios
---
### Enfoque arquitectónico
Uso de una arquitectura **políglota**
- Diferentes tecnologías para distintos problemas
- Separación entre:
- estado en vivo
- persistencia histórica
---
### Objetivo
Construir un sistema:
- escalable
- modular
- alineado con prácticas reales de arquitectura moderna
---
### Tecnologías
- BD relacional -> productos, categorías, usuarios... (**integridad**)
- Redis -> estado activo de las subastas (**velocidad**)
- MongoDB -> almacenamiento histórico (**flexibilidad**)
- APIs REST -> integración entre servicios (**desacoplamiento**)
- Spring Data REST -> exponer repositorios como API (**agilidad**)
---
## MongoDB (Base de datos documental)
### Características principales
- Modelo basado en documentos (JSON / BSON)
- Esquema flexible (no fijo)
- Fácil evolución del modelo de datos
- Soporte natural para estructuras anidadas
---
### Casos de uso
- Datos semiestructurados
- Históricos y auditoría
- Sistemas donde el modelo evoluciona
- APIs modernas (JSON-centric)
---
### Ventajas
- Flexibilidad de diseño
- Alta productividad en desarrollo
- Modelo cercano al dominio de negocio
- Escalabilidad horizontal
### Desventajas
- Menor control de integridad frente a SQL
- Redundancia de datos
- No ideal para transacciones complejas
---
## Redis (Clave-Valor en memoria)
### Características principales
- Base de datos en memoria
- Acceso extremadamente rápido (ms)
- Modelo clave-valor
- Soporte de TTL (expiración automática)
- Estructuras avanzadas (listas, sets, etc.)
### Casos de uso
- Cache, Estado temporal, Sesiones, Sistemas en tiempo real
---
### Ventajas
- Altísimo rendimiento
- Simplicidad de uso
- Ideal para datos efímeros
- TTL nativo
### Desventajas
- Persistencia limitada (según configuración)
- No pensado como almacenamiento principal
- Consumo de memoria
---
## Spring Data REST
### ¿Qué es?
- Componente de Spring que expone automáticamente repositorios como API REST
- Genera endpoints CRUD sin necesidad de controladores
- Basado en HATEOAS (Hypermedia)
### ¿Qué hace?
- Expone entidades directamente como recursos REST
- Genera endpoints como:
- GET /api/items
- GET /api/items/{id}
- Incluye enlaces (_links) para navegación entre recursos
---
#### ¿Cuándo usarlo?
- Prototipos rápidos
- APIs CRUD simples
- Sistemas con bajo control de lógica de negocio
- Cuando se quiere reducir código boilerplate
#### ¿Cuándo NO usarlo?
- Lógica de negocio compleja
- APIs públicas que requieren mayor personalización
- Necesidad de control fino sobre endpoints
- Cuando el modelo interno no debe exponerse directamente
---
## Resolviendo los desafíos
No intentar evitar la complejidad, hay que hacerla explícita y controlarla
- Separación clara de responsabilidades
- Flujo de datos bien definido
- Uso de cada tecnología para lo que mejor sabe hacer
**Diseño orientado a evitar acoplamientos innecesarios**
---
### Separación de responsabilidades
- **Relacional** -> garantiza integridad
- **Redis** -> estado en tiempo real
- **MongoDB** -> persistencia histórica
- **API** -> lógica de negocio
### Beneficios
- Cada componente hace una sola cosa
- Menor complejidad interna por módulo
- Sistema más mantenible
**Evitamos mezclar estado temporal con persistencia**
---
## Control del ciclo de vida de las subastas
#### Problema
- Redis elimina datos al expirar
- No podemos recuperar el estado después
#### Solución
Eliminamos dependencia de eventos internos
- Definimos el tiempo de vida de nuestros eventos
- Introducimos un **scheduler** para gestionar la persistencia
---
### Flujo
1. Subasta activa en Redis
2. Scheduler detecta expiración
3. Persistencia en Mongo
4. Eliminación controlada
**Control explícito del sistema**
---
### Transformación y enriquecimiento
#### Problema
- Datos distribuidos en varios servicios
- Representaciones incompletas
#### Solución
- Feign obtiene entidades base
- Resolución de relaciones
- Construcción de DTO completo (enriquecidos)
---
### Reactividad
**NO es necesaria, pero si conveniente**
- Sistema con múltiples llamadas remotas
- Necesidad de gestionar concurrencia de forma eficiente
- Evitar bloqueos y mejorar rendimiento
---
#### Ventajas
- Mejor uso de recursos
- Alta capacidad de concurrencia
- Código expresivo para flujos complejos
#### Inconvenientes
- Mayor complejidad conceptual
- Manejo cuidadoso de errores
- Debugging más difícil
---
#### ¿En qué casos merece la pena?
- Obtener datos
- Enriquecer información (usuario, categoría, etc.)
- Persistir resultado final
**Todo en un pipeline no bloqueante**
La reactividad es una forma distinta de modelar el flujo del sistema
---
### Resultado
- Independencia de servicios externos
- Gestión de llamadas no bloqueante
- Datos listos para persistencia
- Necesidad de integridad -> sistema relacional
- Ciclo de vida -> Redis
- Snapshot completo redundado -> Mongo
---
---
---
### Todo esto está implementado en:
- **Auction API**
- https://inmaculados.uv.es/dagarcos/bidflow-auction-api
- **Auction Catalog**
- https://inmaculados.uv.es/dagarcos/bidflow-auction-catalog
- **Auction Persistence**
- https://inmaculados.uv.es/dagarcos/bidflow-auction-persistence
- **Auction Users**
- https://inmaculados.uv.es/dagarcos/bidflow-users
- **Bid Client**
- https://inmaculados.uv.es/dagarcos/bidflow-bid-client
Vamos a ver algunas particularidades de la implementación