Logo Google Cloud con Eduardo

Google Cloud con Eduardo

Recibe el código de la lección en tu correo
Te enviaremos el enlace directo al archivo (.zip) y te sumaremos a nuestra newsletter de Google Cloud.

Información básica de protección de datos: Responsable: Eduardo Martínez Agrelo. Finalidad: Facilitar el recurso solicitado y enviar comunicaciones periódicas de valor sobre Google Cloud. Legitimación: Consentimiento del interesado (Art. 6.1.a RGPD). Destinatarios: Plataforma Odoo y proveedores de infraestructura técnica (Google Cloud / Firebase). Derechos: Acceso, rectificación y supresión en eduardomartinezagrelo@gmail.com.
✦ Guía Técnica & Arquitectura

GCP Data Engineer: Arquitectura Enterprise, Lakehouse en BigQuery y Streaming Resiliente

Diseñar plataformas de datos modernas en Google Cloud Platform exige trascender las implementaciones básicas y dominar el desacoplamiento de almacenamiento y cómputo, la resiliencia en streaming mediante Apache Beam y el control estricto de costes con BigQuery FinOps. Esta guía cubre los patrones de arquitectura y decisiones técnicas para niveles Senior y Staff Data Engineers. Para profundizar en el procesamiento streaming con Beam y Dataflow, continúa con Transforma tu Negocio.

Resumen del Blueprint

✓ Arquitectura Medallion & BigLake: Tablas externas con metadatos Iceberg y Delta unificadas en BigQuery.
✓ Streaming con Apache Beam (Dataflow): Manejo de Late Data, Sliding Windows y Dead Letter Queues (DLQ).
✓ BigQuery FinOps: Transición de On-Demand a Editions, optimización de Slots y Storage Write API.
✓ Gobernanza con Dataplex: Data Mesh descentralizado, Data Quality scans y control de acceso a nivel de columna.
Google BigQuery Cloud Dataflow (Apache Beam) Cloud Pub/Sub Cloud Composer (Airflow 2.x) Google Cloud Dataplex dbt-bigquery Terraform GCP Provider

Matriz de Decisión: Motores de Cómputo e Ingesta en GCP

Uno de los desafíos más críticos para un GCP Data Engineer es seleccionar el servicio adecuado según la latencia requerida, el volumen de datos y el modelo de coste operativo (TCO).

Servicio GCP Paradigma & Tipo Latencia Típica Modelo de Coste (FinOps) Caso de Uso Recomendado
BigQuery (Storage Write API) Streaming Ingest / OLAP Sub-segundo (~500ms) Bytes ingeridos ($0.025/GB) + Storage Ingesta directa de microbatches/eventos hacia el Data Warehouse sin transformación compleja.
Cloud Dataflow Streaming / Batch Milisegundos a Minutos vCPU/Hora + Memoria (Dataflow Shuffle / Streaming Engine) Pipelines ETL/ELT con ventanas temporales, enriquecimiento en tiempo real y deduplicación compleja.
Cloud Dataproc (Serverless / Compute) Batch / Micro-batch Minutos a Horas Instancias GCE subyacentes o DCU por segundo Migraciones legacy de Apache Spark, Hadoop o modelos masivos de Machine Learning distribuidos.
BigQuery Scheduled Queries + dbt Batch ELT Minutos a Diario Slots asignados o TB escaneados (On-Demand) Transformaciones analíticas dentro del Data Warehouse (capas Silver y Gold / Data Marts).

Antipatrones Comunes y FinOps en Producción

En proyectos de escala petabyte, un error de diseño puede disparar la factura mensual de Google Cloud en miles de dólares o provocar cuellos de botella en la concurrencia de slots.

Antipatrón Crítico: Escaneo On-Demand sin Particionamiento ni Clustering

El Problema: Ejecutar consultas con SELECT * sobre tablas sin particionar factura la totalidad del tamaño de la tabla (6,25$ por TB escaneado en On-Demand). En tablas con cientos de terabytes, una sola consulta no optimizada ejecutada por un cuadro de mando de BI en Looker puede costar cientos de dólares por ejecución.

La Solución Arquitectónica: Implementar siempre particionamiento por tiempo de ingestión o columna temporal (_PARTITIONDATE / columna TIMESTAMP) combinado con Clustering jerárquico (hasta 4 columnas de alta cardinalidad). Forzar la directiva require_partition_filter = true en Terraform para bloquear consultas globales no acotadas.

Otros errores habituales en pipelines de Google Cloud:

  • Uso de BigQuery Legacy Streaming API (insertAll): Esta API cobra el doble que la Storage Write API, tiene límites de cuota estrictos por proyecto y no garantiza semántica exactly-once nativa sin deduplicación posterior.
  • Dataflow sin Dead Letter Queue (DLQ): Si un mensaje en Pub/Sub llega con un formato JSON corrupto o un tipo de dato incompatible, el worker reintentará infinitamente, bloqueando el avance del watermark y disparando el auto-escalado de Compute Engine.
  • Cloud Composer sobre-dimensionado: Desplegar entornos Cloud Composer (Airflow) con nodos GKE sobredimensionados para tareas que son meramente llamadas API hacia BigQuery (operadores de tipo BigQueryInsertJobOperator). Se debe usar Cloud Composer 2 con auto-escalado de workers a nivel de Celery/Kubernetes.

Implementación Práctica: Pipeline de Streaming Resiliente en Dataflow

El siguiente fragmento de código implementa un pipeline productivo en Python con Apache Beam para ejecutarse en Cloud Dataflow. Lee eventos desde Cloud Pub/Sub, maneja ventanas temporales fijas, enruta anomalías a una Dead Letter Queue (DLQ) mediante Side Outputs y escribe en BigQuery mediante la moderna Storage Write API.

# streaming_pipeline.py
# Pipeline de Streaming para GCP Dataflow con Apache Beam, DLQ y Storage Write API

import json
import logging
import apache_beam as beam
from apache_beam.options.pipeline_options import PipelineOptions, GoogleCloudOptions, StandardOptions, SetupOptions
from apache_beam.transforms.window import FixedWindows
from apache_beam.io.gcp.bigquery import BigQueryDisposition, WriteToBigQuery

# Tag para enrutamiento de errores (Dead Letter Queue)
TAG_DEAD_LETTER = "dead_letter_output"

class ParseAndValidatePayload(beam.DoFn):
    """Transformación que valida el esquema JSON y separa datos corruptos hacia DLQ."""
    
    def process(self, element: bytes):
        try:
            payload = json.loads(element.decode("utf-8"))
            
            # Validación estricta de campos obligatorios
            if "event_id" not in payload or "timestamp" not in payload:
                raise ValueError("Faltan claves primarias obligatorias en el payload.")
                
            # Mutación/Enriquecimiento básico
            payload["processed_by"] = "dataflow-beam-worker"
            yield payload
            
        except Exception as err:
            # Enviar el registro corrupto junto con el mensaje de error a la DLQ
            error_record = {
                "raw_payload": element.decode("utf-8", errors="replace"),
                "error_message": str(err),
                "ingest_timestamp": beam.transforms.window.Timestamp.now().to_rfc3339()
            }
            yield beam.pvalue.TaggedOutput(TAG_DEAD_LETTER, error_record)


def run():
    # Configuración de Opciones de Pipeline para Dataflow
    pipeline_options = PipelineOptions()
    pipeline_options.view_as(StandardOptions).streaming = True
    
    google_cloud_options = pipeline_options.view_as(GoogleCloudOptions)
    google_cloud_options.project = "mi-proyecto-prod-data"
    google_cloud_options.region = "europe-west1"
    google_cloud_options.temp_location = "gs://mi-proyecto-prod-dataflow/temp"
    google_cloud_options.staging_location = "gs://mi-proyecto-prod-dataflow/staging"
    
    input_subscription = "projects/mi-proyecto-prod-data/subscriptions/telemetria-iot-sub"
    target_bq_table = "mi-proyecto-prod-data:lakehouse_bronze.events_telemetry"
    dlq_bq_table = "mi-proyecto-prod-data:lakehouse_bronze.events_dlq"

    with beam.Pipeline(options=pipeline_options) as p:
        
        # 1. Lectura desde Pub/Sub
        raw_events = (
            p 
            | "ReadFromPubSub" >> beam.io.ReadFromPubSub(subscription=input_subscription)
            | "FixedWindow" >> beam.WindowInto(FixedWindows(60))
        )

        # 2. Parseo y división con Side Outputs
        processed_data = (
            raw_events
            | "ParseAndValidate" >> beam.ParDo(ParseAndValidatePayload()).with_outputs(
                TAG_DEAD_LETTER, 
                main="valid_records"
            )
        )

        # 3. Escritura de Registros Válidos mediante BigQuery Storage Write API
        _ = (
            processed_data.valid_records
            | "WriteValidToBigQuery" >> WriteToBigQuery(
                table=target_bq_table,
                schema="event_id:STRING, timestamp:TIMESTAMP, metrics:JSON, processed_by:STRING",
                write_disposition=BigQueryDisposition.WRITE_APPEND,
                create_disposition=BigQueryDisposition.CREATE_IF_NEEDED,
                method=WriteToBigQuery.Method.STORAGE_WRITE_API  # Storage Write API de alto rendimiento
            )
        )

        # 4. Escritura de Errores en la tabla de Dead Letter Queue
        _ = (
            processed_data[TAG_DEAD_LETTER]
            | "WriteDLQToBigQuery" >> WriteToBigQuery(
                table=dlq_bq_table,
                schema="raw_payload:STRING, error_message:STRING, ingest_timestamp:TIMESTAMP",
                write_disposition=BigQueryDisposition.WRITE_APPEND,
                create_disposition=BigQueryDisposition.CREATE_IF_NEEDED,
                method=WriteToBigQuery.Method.STORAGE_WRITE_API
            )
        )

if __name__ == "__main__":
    logging.getLogger().setLevel(logging.INFO)
    run()

Patrones de Diseño: Arquitectura Lakehouse y Medallion en GCP

El modelo arquitectónico estándar para ingeniería de datos en Google Cloud se basa en la combinación de almacenamiento de objetos desacoplado (Cloud Storage / BigLake) con el motor de ejecución analítico de BigQuery.

Estructura de Capas (Medallion Architecture):

  1. Capa Bronze (Raw Ingestion): Almacenamiento de eventos sin transformar procedentes de Cloud Storage o Cloud Pub/Sub. Se utiliza BigQuery Storage Write API o BigLake External Tables sobre formatos Parquet/Iceberg para evitar duplicar costes de almacenamiento.
  2. Capa Silver (Curated & Cleansed): Modelos transformados con dbt-bigquery o Cloud Composer. En esta capa se resuelven duplicidades, se aplican reglas de calidad con Dataplex Data Quality y se definen esquemas con tipos tipificados y control de nulos.
  3. Capa Gold (Business Aggregates / Data Marts): Tablas agregadas y desnormalizadas listas para consumo analítico (Power BI, Looker, Vertex AI). Estas tablas aprovechan el BigQuery BI Engine para acelerar consultas en memoria en sub-segundos sin consumir slots estándar.

Framework de Implementación Paso a Paso en un Entorno Enterprise

  1. 1

    Infraestructura como Código con Terraform

    Define datasets, buckets con retention policies, VPC Service Controls (VPC-SC) para evitar la exfiltración de datos y cuentas de servicio con mínimos privilegios (IAM Least Privilege).

  2. 2

    Diseño del Pipeline de Ingestión Resiliente

    Implementa topics de Pub/Sub con Dead Letter Topics habilitados nativamente y subscripciones de tipo BigQuery Subscription para casos directos o Cloud Dataflow para transformaciones en vuelo.

  3. 3

    Orquestación y Linaje de Datos

    Configura Cloud Composer 2 o Cloud Workflows para coordinar las ejecuciones de dbt, disparar chequeos de validación con Great Expectations / Dataplex y registrar el linaje de datos en Dataplex Catalog.

  4. 4

    Monitoreo, Alertas y FinOps Guardrails

    Establece presupuestos en Google Cloud Billing con alertas en Pub/Sub para pausar slots no esenciales, monitorea el slot_allocation y el retardo del Watermark en Dataflow con Cloud Monitoring dashboards.

Preguntas Frecuentes (FAQ) Técnicas

¿Cuándo conviene elegir BigQuery Editions (Slots) frente al modelo On-Demand en Google Cloud?

El modelo On-Demand es ideal para cargas de trabajo esporádicas o exploratorias (factura 6,25$ por TB escaneado). Sin embargo, cuando el volumen mensual supera de forma sostenida los 50-80 TB o se requieren SLAs predecibles y controles de concurrencia estrictos, se debe migrar a BigQuery Editions (Standard, Enterprise o Enterprise Plus) con Slots Autoscaling o Baseline Reservations. Esto permite acotar el presupuesto máximo mensual, eliminar sorpresas de facturación y aplicar prioridades de ejecución por Workload Management.

¿Por qué la BigQuery Storage Write API reemplaza completamente a la legacy Streaming API (tabledata.insertAll)?

La Storage Write API ofrece semántica de entrega exactly-once mediante streams comprometidos, reduce el coste de ingestión en más de un 50% en comparación con la API heredada insertAll, y utiliza gRPC con compresión binaria Protocol Buffers en lugar de HTTP/JSON. Además, soporta transacciones multilínea dentro de un flujo único y no sufre de las limitaciones de concurrencia y retención de buffer que penalizaban a la API legacy.

¿Cómo gestionar la tolerancia a fallos y evitar atascos en pipelines streaming con Cloud Dataflow y Pub/Sub?

El patrón arquitectónico recomendado es desacoplar los mensajes anómalos mediante un Dead Letter Queue (DLQ) usando Tagged Outputs (Side Outputs) en Apache Beam. Al interceptar fallos de deserialización o validación de esquemas, el payload erróneo se redirige a un tópico secundario de Pub/Sub o a Cloud Storage junto con el stack trace, evitando que el pipeline entre en un bucle infinito de reintentos (poison pills) y se degrade el autoscaling del clúster Dataflow.

Sobre el Autor: Eduardo Martínez Agrelo

AI & Data Architect

Especialista en el diseño de plataformas de datos de alta concurrencia, sistemas distribuidos, arquitecturas Lakehouse y soluciones de Inteligencia Artificial aplicada en entornos cloud empresariales. Creador de contenido formativo técnico y consultor para equipos de ingeniería que escalan infraestructuras analíticas críticas.