lección 2

Día 1 -- Diseñar ingesta de sensor de vibración a escala

Fernando te pide diseñar la ingesta de 720 sensores de vibración de alta frecuencia. Evalúas 3 opciones arquitectónicas, decides schema, particionado y retención. Entregas un ADR completo.

45 min

### Lunes, 8:30 AM -- El brief de Fernando

Datos de apoyo para hoy: abre `datos/lecturas_vibracion_sample.parquet` (columnas `sample_id, sensor_id, machine_id, timestamp, amplitude, axis`) -- es una muestra real de vibración a 50 Hz de 3 sensores que usarás para estimar volumen, validar el schema v2 y razonar el particionado. Cruza con `datos/maquinas.csv` y `datos/sensores.csv` para mapear cada sensor a su máquina y línea.

Es tu tercer día en SmartFactory. Has pasado los dos primeros leyendo código, explorando Grafana y entendiendo el flujo de datos con Kenji. Hoy empieza el trabajo real. Fernando te cita en su despacho a las 8:30 -- un espacio minimalista con vistas a la planta desde el tercer piso. En la pared hay un diagrama de Gantt físico (sí, en papel) con los hitos del trimestre.

1Fernando: "Buenos días. Siéntate. Tengo un problema y necesito tu
2recomendación para mañana a las 10.
3
4Contexto: los sensores de vibracion actuales miden a 1 Hz -- una
5lectura por segundo. Patricia me dice que para detectar degradación
6de rodamientos con tiempo suficiente necesitamos 5 Hz. Eso multiplica
7por 5 el volumen de vibracion: de 520 ev/s a 2.600 ev/s.
8
9Ademas, quiero anadir 200 sensores nuevos en maquinas que hoy no
10tienen instrumentacion de vibracion. Total: 720 sensores a 5 Hz =
113.600 eventos por segundo SOLO de vibracion.
12
13El Kafka actual aguanta en teoria, pero quiero que PIENSES si es la
14mejor opcion o si hay alternativas. Lo que NO quiero es que implementes
15lo primero que se te ocurra.
16
17Entregable: un documento de 1 pagina con 3 opciones, trade-offs en
185 dimensiones y tu recomendación. Lo revisamos mañana a las 10.
19
20Ah, y baja a planta a hablar con Patricia. Ella sabe que datos
21necesita exactamente del sensor de vibracion. No asumas -- pregunta."

Fernando espera una PROPUESTA, no una pregunta. Este es el nivel senior.

### 9:00 AM -- Reunion con Patricia en planta

Bajas al primer piso y cruzas la puerta de seguridad hacía la planta (casco, gafas, tapones obligatorios). Encuentras a Patricia junto a "La Bestia" -- una fresadora CNC de 5 ejes Mazak Integrex, 4 metros de alto, que mecaniza engranajes planetarios con precisión de 3 micras. Patricia tiene un osciloscopio portatil conectado a un acelerometro y estudia la forma de onda.

1Patricia: "Ah, tu eres el nuevo de datos. Ven, mira esto."
2[Senala la pantalla del osciloscopio]
3
4"Ves está onda? Esto es la vibracion de 'La Bestia' en condiciones
5normales. Frecuencia dominante a 180 Hz -- es la velocidad del husillo.
6Amplitud RMS de 2.1 mm/s. Todo normal.
7
8Ahora mira esto..." [cambia a una grabacion guardada]
9
10"Esto es de hace 3 semanas, cuando el rodamiento del husillo empezó
11a degradarse. Ves como aparece un armonico a 720 Hz? Eso es 4x la
12frecuencia del husillo -- es la frecuencia de pasó de bola del
13rodamiento. Cuando ese armonico supera el 30% de la amplitud del
14fundamental, tenemos 24-48 horas antes del fallo.
15
16Lo que necesito del sensor nuevo:
171. Valor RMS de vibracion (ya lo tenemos, pero a 1 Hz pierde el pico)
182. Valor de PICO -- el máximo absoluto en la ventana de muestreo
193. Frecuencia dominante -- para separar vibracion normal de armonicos
204. Temperatura del punto de medicion -- la degradación genera calor
21
22Frecuencia: 5 Hz es lo MINIMO para capturar el armonico. A 1 Hz
23lo perdemos entre muestras. Idealmente 10 Hz, pero se que es mucho
24dato y los de datos siempre os quejais del volumen."
25[Sonrie]
26
27"Latencia: me da igual si tardo 5 minutos en ver la alerta. Lo
28que NO puedo tolerar es perder datos. Si me pierdo la ventana de
29detección por datos perdidos, la maquina falla sin aviso y tengo
30que explicarle a Fernando por que paramos la linea 3 durante 6 horas
31a 36.000 euros la hora."

Patricia te da requisitos EXACTOS. Un buen senior PREGUNTA antes de disenar.

### 10:00 AM -- Reunion con Kenji: contexto técnico

Vuelves a la sala de datos. Kenji te está esperando con un cafe. "Que tal Patricia? Ya te ha enseñado el osciloscopio?" Se rie. "Siempre lo hace con los nuevos. Pero tiene razon -- sabe más de vibraciones que cualquier paper que puedas leer. Ven, te cuento el contexto técnico que necesitas para la propuesta."

1Kenji: "Los sensores nuevos son Siemens MVM-500. Los he mirado ya:
2
3- Soportan MQTT nativo (protocolo IoT estandar, muy ligero)
4- Tambien tienen API REST para configuración y data pull
5- Los actuales publican via un gateway industrial Kepware que
6 convierte OPC-UA a Kafka. Funciona, pero es una caja negra.
7
8Hay basicamente 3 opciones para la ingesta:
9
10Opcion A: Kafka directo via Kepware.
11El gateway actual lee los sensores nuevos y publica a Kafka igual
12que los existentes. Ventaja: no cambias nada en la arquitectura
13downstream. Desventaja: Kepware tiene un límite de 5000 tags y ya
14estamos en 3800. Con 720 sensores nuevos x 4 mediciones = 2880 tags
15más. Nos pasamos del límite.
16
17Opcion B: MQTT a Bridge a Kafka.
18Los MVM-500 publican a un broker MQTT (Mosquitto o EMQX). Un
19conector Kafka-MQTT hace el bridge. Ventaja: MQTT está diseñado
20para IoT, maneja reconexiones y QoS. Desventaja: nuevo componente
21que mantener, equipo no tiene experiencia.
22
23Opcion C: Edge buffer + batch publish.
24Un agente local en el armario de control de cada linea acumula N
25lecturas y publica en batch comprimido a Kafka. Ventaja: reduce
26dramaticamente los mensajes/s en Kafka (de 3600 a ~70). Desventaja:
27anade latencia (10-15 segundos) y complejidad operacional.
28
29Mi opinion? Yo iria por la B, pero no tengo datos para justificarlo.
30Fernando quiere números, no opiniones. Por eso te ha contratado."

Kenji te da el contexto técnico. La decisión es tuya.

### El problema de diseño: marco de evaluación

Tienes toda la información que necesitas. Ahora es tu trabajo sintetizarla en una propuesta estructurada. Como senior, usas un marco de evaluación de 5 dimensiones que te ha servido en todas tus empresas anteriores: rendimiento, fiabilidad, complejidad operacional, coste y evolución futura.

Los números que debes considerar:

  • 720 sensores x 5 Hz = 3.600 eventos/segundo
  • Schema enriquecido con 4 mediciones + metadata = ~320 bytes/mensaje (JSON), ~200 bytes (Avro comprimido)
  • Throughput neto: 3.600 x 320 = 1.15 MB/s en JSON, 0.72 MB/s en Avro
  • Kafka actual: 5 brokers, cada uno soporta ~50 MB/s. Capacidad total: ~250 MB/s. Uso actual: ~12 MB/s
  • Limite Kepware: 5000 tags, uso actual: 3800. Sensores nuevos necesitan 2880 tags adicionales
  • Retencion actual: 72h. A 3.600 ev/s x 320 bytes x 72h = ~300 GB solo en vibracion
  • Presupuesto de Fernando para infra nueva: 5.000 EUR/mes máximo
  • Timeline: 4 semanas desde aprobacion hasta producción

Pensar como senior: cuando evalúes opciones, nunca uses solo una dimensión. Una solución puede ser la más rápida (rendimiento) pero la más difícil de mantener (complejidad). Otra puede ser la más barata hoy pero la que peor escala mañana. Tu trabajo es encontrar el EQUILIBRIO óptimo para ESTE contexto, no la solución "perfecta" en abstracto.

### Decisiones de schema: backward compatibility

Antes de evaluar opciones de transporte, necesitas definir el schema del nuevo evento. El reto: los consumidores actuales de Spark leen el campo "value" (un float con el RMS). Si cambias el schema sin backward compatibility, rompes el pipeline de alertas que lleva 18 meses funcionando. Kenji te mira: "Lo que sea que hagas, no me rompas el streaming de alertas. Si eso se cae a las 3 AM, me llama el coordinador de planta a MI telefono."

1// Schema v2 propuesto -- backward compatible con v1
2// Campos nuevos tienen default para que consumidores v1 no rompan
3{
4 "sensor_id": "SENS-VIB-L03-M047-01",
5 "machine_id": "MACH-L03-047",
6 "line_id": "LINE-03",
7 "plant_id": "PLANT-VIT",
8 "timestamp": "2024-03-15T08:23:41.847Z",
9 "type": "vibration",
10 "value": 4.72,
11 "unit": "mm/s",
12 "measurements": {
13 "rms_mm_s": 4.72,
14 "peak_mm_s": 12.8,
15 "dominant_freq_hz": 2340,
16 "bearing_temp_c": 67.3
17 },
18 "config": {
19 "sample_rate_hz": 5,
20 "axis": "horizontal",
21 "freq_range": "10-5000"
22 },
23 "quality_flag": "GOOD",
24 "metadata": {
25 "firmware_version": "3.0.1",
26 "battery_pct": 87,
27 "signal_strength_dbm": -42,
28 "calibration_date": "2024-01-15"
29 }
30}

Schema v2: el campo "value" se mantiene (legacy) + nuevo objeto "measurements"

La estrategia de compatibilidad es dual-write: el campo "value" sigue conteniendo el RMS (lo que leen los consumidores v1) y el nuevo objeto "measurements" contiene los 4 campos de Patricia. Durante 30 días, ambos coexisten. Los consumidores se migran gradualmente al nuevo formato. Despues de 30 días, el campo "value" se depreca.

### Decisiones de particionado

El particionado en Kafka determina el paralelismo de consumo. Para sensores industriales hay 3 estrategias viables, cada una con implicaciones diferentes en el procesamiento downstream:

  • Por machine_id: todos los datos de una maquina en la misma particion. Pro: correlación entre sensores de una maquina sin shuffle en Spark. Contra: hot partitions si una maquina tiene 15 sensores (75 ev/s) y otra tiene 3 (15 ev/s).
  • Por line_id: datos de una linea completa juntos. Pro: 12 lineas distribuyen uniformemente en 24 particiones (2 por linea). Contra: Patricia necesita correlación por maquina, no por linea -- requiere shuffle.
  • Por sensor_id: máxima distribución, cada sensor en una particion aleatoria. Pro: distribución perfecta. Contra: correlacionar sensores de la misma maquina requiere shuffle masivo en Spark (costoso a 3600 ev/s).

La decisión depende de cómo se consumen los datos. Patricia necesita correlacionar temperatura y vibración de LA MISMA máquina para detectar degradación. Eso sugiere particionar por machine_id. Pero con 340 máquinas y 24 particiones, necesitas una función de hash que distribuya bien: machine_id.hashCode() % 24. El desbalance será moderado (factor 3:1 entre la partición más llena y la más vacía).

Decision crítica: si eliges particionar por line_id (mejor distribución), el pipeline de features de Patricia necesitara un repartition() por machine_id en Spark. A 3.600 ev/s, ese shuffle genera ~4 MB/s de tráfico entre executors. Es manejable, pero es un coste fijo que no existiria con particionado por machine_id. Documenta el trade-off.

### Decisiones de retención: tiered storage

La retención actual de 72 horas en brokers funciona con el volumen actual (~12 MB/s total = ~3 TB en 72h repartidos en 5 brokers). Pero con vibracion a 5 Hz, solo ese topic anade 1.15 MB/s = ~300 GB en 72h. Kenji te comenta: "Fernando quiere minimizar el coste de Kafka sin perder la capacidad de reprocesar si algo falla. Kafka tiene tiered storage desde la versión 3.6 -- primeras N horas en disco local del broker, después se mueve a S3 automaticamente."

Las opciones de retención y su impacto:

  • 24h local + 7 días S3: coste mínimo en brokers (~50 GB/broker para vibracion), recovery window de 7 días. Si Spark falla un fin de semana entero, puedes reprocesar del lunes.
  • 48h local + 7 días S3: cubre un fin de semana parcial en hot storage. Mejor rendimiento de lectura para Spark (disco local vs S3) si hay retraso menor a 2 días.
  • 72h local (sin tiered): actual. Sencillo pero costoso. A 5 Hz necesitas discos más grandes en los brokers o los llenas en días.
  • Solo S3 (Kafka como buffer de 4h): mínimo coste de broker pero peor latencia de lectura para consumidores. No recomendable para streaming de alertas.

Tu recomendación debe considerar que el consumidor de Spark Streaming tiene un SLA de lag máximo de 30 segundos. Si Spark falla, Airflow tiene un DAG de recovery que reprocesa desde el offset almacenado en Kafka. El SLA de recovery es 4 horas. Con tiered storage (24h local + 7d S3) cubres cualquier escenario de fallo razonable sin explotar el disco de los brokers.

## ejercicios

[01]

Architecture Decision Record: ingesta de vibracion

Fernando espera un documento estructurado con 3 opciones evaluadas en 5 dimensiones (rendimiento, fiabilidad, complejidad, coste, evolucion) y tu recomendación final. Escribe el ADR completo como estructura Python. Los números deben ser realistas basados en el contexto: 720 sensores x 5 Hz, ~320 bytes/mensaje, Kafka con 5 brokers.

Cargando editor...
[02]

Schema Avro backward-compatible para vibracion v2

Disena el schema Avro completo para el sensor de vibracion v2. Debe ser backward-compatible con v1 (consumidores existentes no rompen). Incluye los 4 campos de Patricia, metadata y config. Implementa validación y conversión v1->v2.

Cargando editor...
[03]

Configuracion completa de Kafka topic + producer

Configura el topic de Kafka y el producer para 3600 eventos/segundo de vibracion. Incluye: particiones, replicacion, retención tiered, compresión, producer con idempotencia, y cálculo de capacidad de disco.

Cargando editor...
[04]

Configuracion del bridge MQTT-Kafka con batching

Configura el conector Kafka Connect MQTT Source que agrupa eventos del broker EMQX y los publica en Kafka. Incluye: configuración del conector, mapping de topics MQTT a Kafka, batching cada 100ms, y monitoring del bridge.

Cargando editor...
[05]

Capacity planning: escalar a 50M eventos/hora

Fernando quiere saber que necesitas para escalar de 10M a 50M eventos/hora en 12 meses (Pamplona + ultrasonido). Calcula: brokers Kafka necesarios, nodos Spark, storage, y coste total. Presenta como tabla comparativa actual vs target.

Cargando editor...

Regístrate para guardar tu progreso.

## comentarios

Reporta erratas, ayuda a otros o comparte tu opinión. Sé constructivo.

Inicia sesión para comentar y responder.

cargando comentarios...