El Modelo Mental de Procesamiento por Lotes, en Streaming y Orquestación
Cada pipeline de datos, sin importar la herramienta que lo construya, responde a las mismas tres preguntas.
Busca en todas las páginas de la documentación
Cada pipeline de datos, sin importar la herramienta que lo construya, responde a las mismas tres preguntas.
¿Cuántos datos procesa una ejecución de este pipeline: un fragmento delimitado o un flujo continuo e ilimitado?
¿Qué decide cuándo y en qué orden se ejecuta cada paso de este pipeline?
¿Y qué sucede la segunda vez que un paso se ejecuta sobre la misma entrada, ya sea por un reintento, un backfill o un mensaje reentregado?
Fundamentos de Ingeniería de Datos muestra la API concreta para construir trabajos por lotes y en streaming; esta página trata sobre los tres conceptos subyacentes a cada uno de ellos: lotes frente a streaming como una compensación, el DAG como un grafo de dependencias en lugar de un planificador, y la idempotencia como la propiedad que hace que la recuperación de fallos sea segura.
Un pipeline por lotes procesa un conjunto de datos delimitado y de tamaño conocido - "los pedidos de ayer", "los archivos de registro de este mes" - y finaliza; volver a ejecutarlo más tarde procesa el siguiente fragmento delimitado.
Un pipeline en streaming procesa una secuencia ilimitada de eventos a medida que llegan, sin un "final" natural al que esperar, lo que significa que debe producir resultados útiles de forma continua en lugar de después de un pase completo sobre los datos.
Esta es una compensación genuina, no solo dos implementaciones de la misma idea: el procesamiento por lotes puede ver todos los datos antes de decidir una respuesta (un total de un día completo, una unión completa), mientras que el procesamiento en streaming tiene que responder solo con lo que ha llegado hasta el momento, aceptando que los datos que llegan tarde pueden necesitar ser reconciliados después.
Un DAG (grafo dirigido acíclico) es la segunda idea central: es un grafo de tareas y dependencias - "la tarea B necesita la salida de la tarea A" - sin ciclos, y fundamentalmente, un DAG define qué depende de qué, no cuándo se ejecutan las cosas.
Una lectura errónea común es pensar en un DAG como una secuencia fija, como una lista numerada de pasos; en realidad, un planificador es libre de ejecutar dos tareas cualesquiera sin dependencia entre ellas en paralelo, o en cualquier orden, siempre que las dependencias declaradas de cada tarea se completen primero.
La orquestación es la capa que convierte una definición de DAG en ejecución real: decide qué tareas están listas para ejecutarse (sus dependencias se satisfacen), reintenta las tareas fallidas y rastrea el estado de cada ejecución; esto es distinto de la planificación simple, que solo decide cuándo comienza un trabajo, sin noción de dependencia entre trabajos.
La idempotencia es la propiedad de que ejecutar una operación dos veces con la misma entrada produce el mismo resultado que ejecutarla una vez, y es la propiedad que hace que cada reintento, backfill y mensaje reentregado sea seguro en lugar de peligroso.
La elección entre lotes y streaming y el requisito de idempotencia están más conectados de lo que parecen inicialmente: cualquier sistema de streaming que prometa entrega fiable bajo fallo tiene que reentregar mensajes a veces, y solo el procesamiento idempotente hace que esa reentrega sea inofensiva en lugar de duplicar datos.
Los sistemas de streaming en su mayoría ofrecen entrega al menos una vez por defecto: un mensaje puede ser procesado más de una vez después de un fallo y reinicio, porque reconocer "procesé esto" y "confirmar el resultado" no se puede hacer perfectamente atómico entre dos sistemas diferentes (el intermediario de mensajes y el sink de salida) sin coordinación adicional.
El procesamiento exactamente una vez, cuando se afirma, generalmente se logra combinando la entrega al menos una vez con un sink idempotente; por ejemplo, escribir resultados con clave por un ID de mensaje para que una escritura duplicada simplemente sobrescriba la misma fila en lugar de agregar una segunda, no por alguna garantía de nivel inferior de que los duplicados nunca ocurran.
Una marca de agua (watermark) es cómo los sistemas de streaming razonan sobre "suficientemente hecho": dado que un flujo nunca termina realmente, una marca de agua es una afirmación heurística de que probablemente han llegado todos los datos hasta algún punto en el tiempo del evento, lo que permite que las agregaciones por ventanas (como "eventos por ventana de 5 minutos") finalicen un resultado mientras se acepta que una pequeña fracción de datos muy tardíos pueden perderse o manejarse por separado.
Los orquestadores por lotes se enfrentan a una versión paralela del mismo problema de idempotencia: si un trabajo nocturno falla a mitad de camino y se reintenta, agregar su salida parcial una segunda vez contaría las filas dos veces; la solución estándar es hacer que la salida de cada ejecución esté claveada por una partición estable (una fecha, un ID de lote) y que el trabajo sobrescriba esa partición en lugar de agregar ciegamente.
Los orquestadores basados en DAG (Airflow, Prefect, Dagster) también codifican cuánta historia representa una ejecución de tarea mediante un intervalo de datos, que es el rango de tiempo lógico que representa una ejecución, lo que permite que un backfill reejecute las ejecuciones del DAG del mes pasado y obtenga los datos del mes pasado, en lugar de procesar accidentalmente los datos de hoy bajo la etiqueta de ayer.
# un DAG expresa dependencia, no orden de ejecución:
# extract_orders y extract_customers no tienen dependencia entre sí,
# por lo que un orquestador es libre de ejecutarlos concurrentemente
extract_orders >> transform_orders
extract_customers >> transform_orders # transform espera a AMBAS tareas upstream
transform_orders >> load_warehouse # load solo comienza una vez que transform finalizaA escala, la elección entre lotes y streaming deja de ser binaria y se convierte en un espectro: los sistemas de micro-lotes (structured streaming en PySpark, por ejemplo) procesan fragmentos delimitados pequeños y frecuentes, intercambiando parte de la latencia del streaming por el razonamiento más simple de datos delimitados del procesamiento por lotes.
Elegir entre Airflow, Prefect y Dagster es menos sobre qué motor de DAG es "mejor" y más sobre qué unidad de abstracción coincide con el modelo mental del equipo: Airflow se centra en tareas y operadores, Prefect se centra en funciones Python simples con anotaciones ligeras, y Dagster se centra en los activos de datos (las salidas que produce un pipeline) en lugar de las tareas que los producen.
La validación de datos pertenece como un nodo de primera clase en el DAG, no como una ocurrencia tardía: un pipeline que carga datos incorrectos según lo programado a menudo es peor que uno que falla ruidosamente, porque los consumidores posteriores (paneles, características de ML, otros pipelines) pueden confiar en la salida sin saber que es incorrecta.
La observabilidad para los pipelines tiene que responder preguntas que el monitoreo por lotes y el monitoreo en streaming hacen de manera diferente: el procesamiento por lotes pregunta "¿terminó esta ejecución y cómo se compararon sus recuentos de filas con el historial?", mientras que el procesamiento en streaming pregunta "¿cuánto retraso tiene este consumidor?" (retraso del consumidor) y "¿cuántos mensajes están atascados en una cola de mensajes muertos?".
La elección del formato de archivo interactúa con todo esto: los formatos columnares como Parquet admiten la poda de particiones y la inserción de predicados que hacen que los patrones de sobrescritura de particiones idempotentes sean baratos, mientras que los formatos orientados a filas hacen que el reprocesamiento selectivo de solo una partición sea mucho más costoso.
| Enfoque | Fortaleza | Debilidad | Mejor Ajuste |
|---|---|---|---|
| Por Lotes | Razonamiento simple, puede ver todos los datos antes de responder, backfills fáciles | Latencia medida en minutos-horas; obsoleto por definición entre ejecuciones | Informes programados, backfills históricos, agregación no crítica en tiempo |
| Micro-lotes | Une la simplicidad de lotes con entrega casi en tiempo real | Todavía agrega un piso de latencia de planificación/disparo; no es verdaderamente impulsado por eventos | Paneles casi en tiempo real donde la latencia de segundos a minutos es aceptable |
| En Streaming | Latencia más baja, reacciona a eventos individuales | Requiere marcas de agua/ventanas, más difícil de razonar sobre "hecho", sobrecarga de gestión de estado | Detección de fraude, alertas en tiempo real, arquitecturas impulsadas por eventos |
| Orquestación DAG (Airflow/Prefect/Dagster) | Grafo de dependencia explícito, reintentos, backfills, planificación en un solo sistema | Agrega un sistema operativo para ejecutar y monitorear; excesivo para un script lineal simple | Pipelines de múltiples pasos con dependencias de tareas reales entre fuentes |
No directamente: un DAG define las dependencias entre tareas, y un orquestador es libre de ejecutar dos tareas cualesquiera sin dependencia entre ellas de forma concurrente o en cualquier orden, siempre que todas las dependencias ascendentes declaradas de cada tarea hayan finalizado primero.
La planificación decide cuándo se inicia un trabajo (un disparador tipo cron), mientras que la orquestación además rastrea las dependencias entre tareas, reintenta fallos y gestiona el estado de la ejecución de todo un DAG; un planificador sin modelo de dependencia no es un orquestador.
Los fallos son rutinarios en los pipelines distribuidos: los trabajadores se caen, las redes se particionan, los mensajes se reentregán; y la idempotencia es lo que convierte "esta tarea se ejecutó dos veces" de un evento que corrompe datos a una operación nula inofensiva, que es lo que hace que los reintentos automáticos y los backfills sean seguros de ejecutar sin limpieza manual.
Una marca de agua es una afirmación heurística de que probablemente han llegado todos los eventos hasta un cierto punto en el tiempo del evento, lo que permite que una agregación por ventanas (como un recuento de 5 minutos) finalice y emita un resultado en lugar de esperar para siempre datos que teóricamente aún podrían llegar tarde.
Escribiendo la salida limitada a una clave de partición estable (una fecha, un ID de ejecución, un intervalo de datos) y sobrescribiendo esa partición en lugar de anexarla, de modo que una ejecución reintentada reemplace su propia salida previa (posiblemente parcial) en lugar de duplicar filas junto a ella.
Airflow centra su modelo en tareas y operadores conectados en un DAG; Prefect se centra en funciones Python ordinarias con una ligera decoración para el seguimiento de dependencias; Dagster se centra en los activos de datos que produce un pipeline en lugar de las tareas que los producen; los tres todavía orquestan DAGs de trabajo dependiente por debajo.
El micro-lote encaja cuando la salida casi en tiempo real es importante (segundos a minutos, no horas), pero el equipo quiere seguir razonando sobre pequeños fragmentos delimitados en lugar de construir una infraestructura de streaming completa con marcas de agua y consumidores con estado de larga duración.
Un pipeline que "tiene éxito" mientras carga datos inválidos, incompletos o duplicados es a menudo más perjudicial que uno que falla ruidosamente, porque los consumidores descendentes no tienen ninguna señal para desconfiar de la salida; es por eso que la validación de datos se trata como un nodo DAG con su propio estado de aprobación/fallo, no como una verificación secundaria.
El retraso del consumidor es la brecha entre el último mensaje producido en un flujo y el último mensaje que un consumidor dado ha procesado; un retraso creciente significa que el consumidor no puede seguir el volumen entrante, lo que es una señal de advertencia temprana antes de que un pipeline se quede visiblemente atrás o pierda datos.
Solo en el sentido trivial de que una secuencia estricta es técnicamente un grafo de dependencia (lineal); el valor práctico de un orquestador DAG real se muestra una vez que hay ramas genuinamente independientes que podrían ejecutarse en paralelo, o tareas que necesitan reintentos, backfills y planificación consciente de dependencias para las cuales un script simple no tiene marco.
Los formatos columnares como Parquet admiten la poda de particiones, por lo que sobrescribir o reprocesar solo una partición (una fecha, un rango de claves) solo toca los archivos relevantes; los formatos orientados a filas como CSV generalmente requieren reescribir o escanear un archivo completo incluso para arreglar una partición, lo que hace que el reprocesamiento parcial idempotente sea mucho más costoso.
Versiones de Stack: Esta página fue escrita para Python 3.14 (estable) / 3.13 (mantenimiento); los conceptos (lotes/streaming, DAGs, idempotencia) son agnósticos a la herramienta y no están vinculados a una versión específica de orquestador o biblioteca de procesamiento de flujos.
Revisado por Chris St. John·Última actualización: 15 jul 2026