El problema que resuelven
Queremos dos cosas a la vez que parecen contradictorias:
- Resultados exactos y completos sobre todo el histórico (lo que batch hace bien).
- Resultados frescos, con segundos de retraso como máximo (lo que streaming hace bien).
¿Cómo tener ambas? Las arquitecturas Lambda y Kappa son dos respuestas distintas a esta pregunta.
Arquitectura Lambda
Propuesta por Nathan Marz, la arquitectura Lambda combina dos rutas de procesamiento en paralelo sobre los mismos datos:
- Batch layer (capa batch): almacena el dataset maestro inmutable y recalcula periódicamente (cada hora, cada noche) las vistas batch sobre todos los datos. Es exacta pero lenta.
- Speed layer (capa de velocidad): procesa en streaming solo los datos recientes —los que aún no cubre la última vista batch— produciendo vistas en tiempo real. Es rápida pero aproximada.
- Serving layer (capa de servicio): responde las consultas combinando la vista batch con la vista incremental:
consulta = vista_batch + vista_tiempo_real.
graph TD F["Fuentes de datos<br/>(eventos)"] --> IM["Datos inmutables<br/>(dataset maestro)"] IM --> BL["Batch layer<br/>recalcula todo<br/>periódicamente"] F --> SL["Speed layer<br/>procesa lo reciente<br/>en streaming"] BL --> BV["Vistas batch<br/>(exactas, antiguas)"] SL --> RV["Vistas en tiempo real<br/>(aproximadas, frescas)"] BV --> SV["Serving layer"] RV --> SV SV --> Q["Consultas<br/>batch + tiempo real"]
Un ejemplo clásico: contar las visitas por página. La batch layer recalcula cada noche los totales históricos exactos; la speed layer mantiene un contador incremental con lo ocurrido desde medianoche; la serving layer suma ambos.
Ventajas y desventajas de Lambda
| Ventajas | Desventajas |
|---|---|
| Resultados exactos sobre todo el histórico | Dos bases de código (batch y streaming) que deben dar el mismo resultado |
| La batch layer corrige los errores de la speed layer en cada recomputación | Doble operación y mantenimiento: cada cambio de lógica se hace dos veces |
| Tolerancia a fallos humanos: al recomputar desde datos inmutables se arreglan bugs | Complejidad en la reconciliación de vistas |
La crítica habitual a Lambda: la lógica de negocio duplicada en dos frameworks distintos (por ejemplo, Spark batch y Flink streaming) tiende a divergir con el tiempo.
Arquitectura Kappa
Propuesta por Jay Kreps (cocreador de Kafka), Kappa plantea una simplificación radical: todo es un stream. Solo hay una capa:
- Todos los datos entran como un flujo de eventos en un log inmutable y durable (típicamente Kafka) con retención larga.
- Un único motor de stream processing mantiene las vistas actualizadas continuamente.
- Si cambia la lógica o hay que corregir un bug, se hace replay: se relanza el procesamiento leyendo el log desde el principio (offset 0) hacia unas vistas nuevas, y se cambia el puntero cuando estén listas.
graph TD F["Fuentes de datos<br/>(eventos)"] --> LOG["Log inmutable<br/>(Kafka, retencion larga)"] LOG --> SP["Stream processing<br/>(una sola logica)"] SP --> V["Vistas materializadas"] V --> Q["Consultas"] LOG -. "replay desde<br/>offset 0 si cambia<br/>la logica" .-> SP2["Nueva version del<br/>stream processing"] SP2 --> V2["Vistas nuevas"] V2 --> Q
La idea clave de Kappa: una batch layer no es más que un stream job que lee un stream “muy largo”. Si tu log guarda todo el histórico, no necesitas una capa aparte.
Ventajas y desventajas de Kappa
| Ventajas | Desventajas |
|---|---|
| Una sola base de código y un solo framework | El log debe retener todo el histórico: almacenamiento caro |
| No hay reconciliación: una sola fuente de resultados | Recomputar todo el histórico (replay) puede ser muy costoso |
| Modelo mental simple: todo es un stream | No todos los cálculos se expresan de forma natural como streaming (joins complejos, ML batch) |
¿Cuándo elegir cada una?
| Situación | Recomendación |
|---|---|
| Lógica batch y tiempo real muy distintas, o algoritmos que solo funcionan en batch | Lambda |
| La misma lógica sirve para datos históricos y en vivo | Kappa |
| El equipo domina un solo stack de streaming (Flink, Spark Structured Streaming) | Kappa |
| Volumen de histórico enorme y recomputarlo todo es prohibitivo | Lambda (batch sobre almacenamiento barato) |
| Correcciones frecuentes de lógica con necesidad de replay rápido | Kappa (con particionado suficiente para recompute rápido) |
En la práctica, con motores modernos como Flink o Spark Structured Streaming —que ejecutan el mismo código en modo batch y streaming— la frontera se difumina y muchas organizaciones se inclinan por Kappa.
Ejercicio: reconciliar batch layer + speed layer
🧪 Ejercicio
Vista batch + vista incremental
Simula la reconciliación de una arquitectura Lambda. Tienes `historico` (eventos antiguos ya procesados por la batch layer) y `recientes` (eventos llegados después de la última recomputación). Implementa: 1) `vista_batch(eventos)` que cuente eventos por categoría, 2) `vista_speed(eventos)` igual pero sobre los recientes, y 3) `consultar(vb, vs)` que combine ambas sumando conteos. Muestra la vista final y comprueba que coincide con contar todo junto.
🔍 Para combinar dos diccionarios de conteos, recorre las claves de ambos y suma.
def contar_por_categoria(eventos):
conteo = {}
for cat in eventos:
conteo[cat] = conteo.get(cat, 0) + 1
return conteo
# La batch layer corre de noche sobre el historico
historico = ["compra", "visita", "visita", "compra", "clic"]
vista_batch = contar_por_categoria(historico)
# La speed layer cubre solo lo llegado desde entonces
recientes = ["visita", "compra"]
vista_speed = contar_por_categoria(recientes)
# Serving layer: reconcilia sumando ambas vistas
def consultar(vista_batch, vista_speed):
total = dict(vista_batch)
for cat, n in vista_speed.items():
total[cat] = total.get(cat, 0) + n
return total
resultado = consultar(vista_batch, vista_speed)
print("Vista reconciliada:", resultado)
# Verificacion: debe coincidir con contar todo de golpe
esperado = contar_por_categoria(historico + recientes)
print("Esperado: ", esperado)
assert resultado == esperado, "Las vistas no coinciden"
print("Reconciliacion correcta")Comprueba lo aprendido
Comprueba que lo pillaste
En una arquitectura Lambda, ¿qué capa corrige las posibles aproximaciones o errores de la speed layer?
La batch layer recalcula las vistas desde cero sobre el dataset maestro inmutable, así que cada recomputación reemplaza los resultados aproximados de la speed layer con valores exactos.
Comprueba que lo pillaste
¿Qué necesita la arquitectura Kappa para poder prescindir de la batch layer?
Kappa sustituye la recomputación batch por replay: relanzar el stream job desde el offset 0. Eso solo es posible si el log (Kafka) retiene todo el histórico de eventos.
Comprueba que lo pillaste
¿Cuál es la principal crítica operativa a la arquitectura Lambda?
Lambda exige implementar la misma lógica de negocio dos veces, en stacks distintos, y mantenerlas sincronizadas. Esa duplicación es su coste principal y la motivación de Kappa.
Resumen
- Lambda combina una batch layer (exacta, sobre todo el histórico), una speed layer (fresca, sobre lo reciente) y una serving layer que reconcilia ambas vistas.
- Su coste principal es mantener dos implementaciones de la misma lógica.
- Kappa simplifica a una sola capa de streaming sobre un log durable; el replay desde el offset 0 sustituye a la batch layer.
- Kappa exige retener todo el histórico en el log y que la lógica sea expresable como streaming.
- La elección depende del volumen del histórico, del stack del equipo y de si la lógica batch y streaming son realmente la misma.
📚 Lecturas y fuentes
| Recurso | Tipo | Por qué leerlo |
|---|---|---|
| Macrodatos (Wikipedia en español) | Artículo | Para situar estas arquitecturas en el panorama general: lee solo la sección “Arquitectura”. |
| Questioning the Lambda Architecture (Jay Kreps, 2014) | Artículo | El texto que propuso Kappa. Corto y polémico: léelo entero, es la fuente directa de la crítica a Lambda que vimos. (en inglés) |
| Lambda architecture (Wikipedia en inglés) | Artículo | Descripción neutral de las tres capas y un resumen de las críticas. Lee “Batch layer”, “Speed layer”, “Serving layer” y “Criticism”. (en inglés) |
| Event Sourcing (Martin Fowler) | Artículo | El patrón que hace posible el replay de Kappa. Lee “How it Works” y “When to Use It”; los ejemplos en Java son opcionales. (en inglés) |