lección 5
Apache Kafka: instalar con Docker y entender los fundamentos
Levanta un cluster Kafka con Docker, entiende topics, particiones, brokers y produce/consume tus primeros mensajes.
⏱ 55 min
### Kafka: la autopista de datos que mueve el mundo
Si SQS es un buzón de correos y EventBridge es una centralita de hotel, Kafka es una AUTOPISTA DE DATOS. Una infraestructura industrial diseñada para mover MILLONES de mensajes por segundo con latencia de milisegundos. LinkedIn la creó en 2011 porque necesitaba procesar la actividad de 700 millones de usuarios en tiempo real. Hoy, Kafka mueve datos en Netflix, Uber, Airbnb, Goldman Sachs, y prácticamente cualquier empresa con flujos de datos a escala.
¿Por qué existe Kafka si ya teníamos colas como RabbitMQ o SQS? Porque las colas tradicionales tienen un modelo "consume y desaparece": cuando un consumidor lee un mensaje, se borra. Kafka es diferente: los mensajes se PERSISTEN en disco durante días o semanas. Múltiples consumidores pueden leer el MISMO mensaje. Puedes "rebobinar" y releer desde el principio. Es un LOG DISTRIBUIDO, no una cola.
### La analogía del periódico vs el buzón
SQS es como un buzón: recibes una carta, la lees, la tiras. Nadie más puede leerla. Kafka es como un periódico: se publica UNA VEZ, pero miles de personas lo leen independientemente. El periódico no desaparece cuando tú lo lees — sigue disponible para los demás. Y si llegaste tarde, puedes ir a la hemeroteca y leer ediciones anteriores (replay). Eso es Kafka: un log inmutable y persistente que múltiples consumidores leen a su propio ritmo.
### Los conceptos fundamentales de Kafka
- TOPIC: canal con nombre donde se publican mensajes. Equivale al "tema" del periódico (deportes, economía, etc.).
- PARTITION: subdivisión de un topic para paralelismo. Cada partición es un log ordenado e inmutable.
- BROKER: un servidor Kafka. Un cluster tiene múltiples brokers para redundancia.
- PRODUCER: quien escribe mensajes en un topic.
- CONSUMER: quien lee mensajes de un topic.
- OFFSET: posición del consumidor en una partición. "Voy por el mensaje 4.237 de 10.000".
- CONSUMER GROUP: grupo de consumidores que se reparten las particiones. Paralelismo coordinado.
### Instalar Kafka con Docker Compose
Kafka necesita un servicio de coordinación. Históricamente era ZooKeeper, pero desde Kafka 3.3+ existe KRaft (Kafka Raft) que elimina esa dependencia. Usaremos KRaft porque es el futuro y simplifica el setup. Un solo contenedor Docker con Kafka en modo KRaft es suficiente para aprender.
1# Crear carpeta de trabajo2# Windows (PowerShell):3mkdir kafka-lab; cd kafka-lab45# Mac (Terminal):6mkdir kafka-lab && cd kafka-lab
Crear el directorio del laboratorio Kafka
1# docker-compose.yml para Kafka con KRaft (sin ZooKeeper)2cat > docker-compose.yml << 'EOF'3services:4 kafka:5 image: confluentinc/cp-kafka:7.6.06 hostname: kafka7 container_name: kafka-broker8 ports:9 - "9092:9092"10 environment:11 KAFKA_NODE_ID: 112 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT13 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:909214 KAFKA_LISTENERS: PLAINTEXT://kafka:29092,CONTROLLER://kafka:29093,PLAINTEXT_HOST://0.0.0.0:909215 KAFKA_CONTROLLER_LISTENER_NAMES: CONTROLLER16 KAFKA_CONTROLLER_QUORUM_VOTERS: 1@kafka:2909317 KAFKA_PROCESS_ROLES: broker,controller18 KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 119 KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 120 KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 121 KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 022 KAFKA_LOG_RETENTION_HOURS: 16823 CLUSTER_ID: MkU3OEVBNTcwNTJENDM2Qk24 volumes:25 - kafka-data:/var/lib/kafka/data26volumes:27 kafka-data:28EOF
docker-compose.yml: Confluent Platform 7.6 (Apache Kafka 3.6) con KRaft. Un broker, perfecto para desarrollo.
1# Levantar Kafka2# Windows (PowerShell) y Mac (Terminal):3docker compose up -d45# Verificar que está corriendo:6docker compose ps78# Esperar ~15 segundos a que arranque completamente9# Verificar que responde:10docker exec kafka-broker kafka-topics --bootstrap-server localhost:9092 --list1112# Si no hay error, Kafka está listo.
Levantar y verificar el cluster Kafka
### Crear tu primer topic
Un topic es el canal donde se publican los mensajes. Es como una carpeta con nombre. Vamos a crear un topic "pedidos" con 3 particiones. ¿Por qué 3 particiones? Porque cada partición puede ser consumida por un consumidor diferente en paralelo. 3 particiones = hasta 3 consumidores procesando en paralelo.
1# Crear un topic con 3 particiones2docker exec kafka-broker kafka-topics --bootstrap-server localhost:9092 \3 --create --topic pedidos --partitions 3 --replication-factor 145# Verificar que se creó:6docker exec kafka-broker kafka-topics --bootstrap-server localhost:9092 \7 --describe --topic pedidos89# Salida esperada:10# Topic: pedidos Partitions: 3 ReplicationFactor: 111# Partition: 0 Leader: 1 Replicas: 1 Isr: 112# Partition: 1 Leader: 1 Replicas: 1 Isr: 113# Partition: 2 Leader: 1 Replicas: 1 Isr: 1
Crear un topic "pedidos" con 3 particiones
### Producir y consumir desde la terminal
Kafka incluye herramientas de línea de comandos para producir y consumir. Vamos a usarlas primero para ver el flujo antes de programar en Python.
1# Terminal 1 — Consumidor (escucha desde el principio):2docker exec -it kafka-broker kafka-console-consumer \3 --bootstrap-server localhost:9092 \4 --topic pedidos \5 --from-beginning67# Terminal 2 — Productor (escribe mensajes):8docker exec -it kafka-broker kafka-console-producer \9 --bootstrap-server localhost:9092 \10 --topic pedidos1112# Escribe mensajes y pulsa Enter:13# > {"pedido_id": "ORD-001", "total": 49.99}14# > {"pedido_id": "ORD-002", "total": 129.00}15# > {"pedido_id": "ORD-003", "total": 15.50}16# Verás los mensajes aparecer en la Terminal 1 instantáneamente.
Producir y consumir desde la CLI: la forma más rápida de verificar que funciona
### Producir desde Python con kafka-python
1# Instalar la librería kafka-python2# Windows (PowerShell) y Mac (Terminal):3pip install kafka-python
Instalar kafka-python en tu entorno virtual
1from kafka import KafkaProducer2import json3import time45# Crear productor6producer = KafkaProducer(7 bootstrap_servers=["localhost:9092"],8 value_serializer=lambda v: json.dumps(v).encode("utf-8"),9 key_serializer=lambda k: k.encode("utf-8") if k else None,10)1112# Producir 10 mensajes13for i in range(10):14 pedido = {15 "pedido_id": f"ORD-{1000 + i}",16 "cliente_id": f"CLI-{i % 5}",17 "total": round(20 + i * 15.5, 2),18 "timestamp": time.time(),19 }20 # La KEY determina a qué partición va el mensaje21 future = producer.send(22 topic="pedidos",23 key=pedido["cliente_id"], # Misma key = misma partición24 value=pedido,25 )26 metadata = future.get(timeout=10)27 print(f"Enviado: {pedido['pedido_id']} -> partition={metadata.partition} offset={metadata.offset}")2829producer.flush()30producer.close()31print("\nProductor finalizado. 10 mensajes enviados.")
Productor Python: la KEY decide en qué partición aterriza cada mensaje
### Consumir desde Python
1from kafka import KafkaConsumer2import json34consumer = KafkaConsumer(5 "pedidos",6 bootstrap_servers=["localhost:9092"],7 auto_offset_reset="earliest", # Leer desde el principio8 group_id="mi-primer-grupo",9 value_deserializer=lambda m: json.loads(m.decode("utf-8")),10)1112print("Consumidor escuchando topic 'pedidos'...")13count = 014for message in consumer:15 pedido = message.value16 print(f" [{message.partition}:{message.offset}] {pedido['pedido_id']} - {pedido['total']}EUR")17 count += 118 if count >= 10:19 break2021consumer.close()22print(f"\nConsumidos {count} mensajes.")
Consumidor Python: lee mensajes indicando partición y offset de cada uno
### La KEY y la distribución entre particiones
La KEY del mensaje es FUNDAMENTAL en Kafka. Determina en qué partición aterriza el mensaje (mediante murmur2(key) % num_particiones — no el hash() de Python, que cambia en cada proceso). Mensajes con la MISMA key van SIEMPRE a la MISMA partición. ¿Por qué importa? Porque dentro de una partición el ORDEN está garantizado. Si quieres que todos los eventos de un mismo cliente se procesen en orden, usa el cliente_id como key. Todos irán a la misma partición y se consumirán en secuencia.
Si no especificas key (key=None), el reparto depende del cliente: kafka-python elige partición al azar, y el cliente de Java (desde 2.4) usa un partidor "sticky" que llena un lote y luego cambia. En ambos casos, máxima distribución y cero garantía de orden entre mensajes del mismo cliente.
Consejo de senior: elige la key con CUIDADO. Una key con poca cardinalidad (ej. "país" con 4 valores) crea particiones desbalanceadas — una partición tiene el 80% del tráfico. Una key con alta cardinalidad (ej. pedido_id) distribuye uniformemente pero pierde ordenación por cliente. La key ideal es el "agregado" que quieres ordenar: cliente_id, cuenta_id, dispositivo_id.
Lo que le diría a mi yo de hace 5 años: el número de particiones es DIFÍCIL de cambiar después. Si creas un topic con 3 particiones y mañana necesitas 10, puedes añadirlas pero los mensajes existentes NO se redistribuyen. Planifica desde el inicio: para producción, piensa en el throughput máximo esperado.
Kafka no garantiza orden ENTRE particiones, solo DENTRO de una partición. Si tu topic tiene 3 particiones, los mensajes de particiones diferentes pueden llegar en cualquier orden al consumidor. No asumas orden global.
## ejercicios
Productor Kafka: stream de ventas Black Friday
Es Black Friday y el e-commerce genera 1 venta por segundo. Escribe un productor que envíe 20 eventos de venta al topic "ventas-blackfriday" con key=tienda_id (hay 4 tiendas). Cada venta tiene: venta_id, tienda_id, producto, precio, timestamp. Qué deberías ver: 20 líneas con venta_id, tienda, partición y offset. Las ventas de la misma tienda siempre caen en la misma partición.
Consumidor Kafka: leer ventas y calcular total por tienda
Escribe un consumidor que lea del topic "ventas-blackfriday" desde el inicio y calcule el total vendido por cada tienda. Usa auto_offset_reset="earliest" y group_id="analytics-v1". Qué deberías ver: una línea por cada mensaje con partición, offset, venta_id, tienda y precio; al final, el resumen de ventas por tienda con el total en EUR.
Explorar topics y particiones con la CLI
Usa los comandos CLI de Kafka para: 1) Listar todos los topics, 2) Describir el topic "pedidos" (ver particiones y réplicas), 3) Ver el offset actual de cada partición del topic "pedidos". Qué deberías ver: --list muestra los topics creados; --describe muestra 3 particiones con Leader:1, Replicas:1, Isr:1; kafka-get-offsets muestra pedidos:0:N pedidos:1:N pedidos:2:N con los offsets actuales.
Verificar que la key dirige a la misma partición
Produce 10 mensajes con key="cliente-A", 10 con key="cliente-E" y 10 con key="cliente-F". Verifica que cada key va siempre a la misma partición y que las tres caen en particiones distintas (con 3 particiones y murmur2, estas keys reparten 0/1/2). Qué deberías ver: los 10 de cliente-A siempre en la misma partición, los de cliente-E en otra, y los de cliente-F en la tercera.
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...