Kafka en producción: particiones, lag, fiabilidad y respuesta a incidentes

Una guía práctica para tomar decisiones de orden, capacidad y recuperación en Kafka, interpretar el lag y responder a fallos sin perder de vista el resultado de negocio.
Una demostración de Kafka termina cuando el productor envía un mensaje y el consumidor lo imprime. Un sistema de producción tiene que seguir siendo comprensible cuando falla un broker, se atasca un consumidor o cambia el esquema de un evento. Lo difícil no es lograr que circule un mensaje: es definir qué debe mantenerse ordenado, cuánto retraso se tolera y cómo se recupera un efecto de negocio incorrecto.
Usaremos una plataforma de pedidos con el tema orders.placed.v1, un grupo de consumidores para inventario y otro para análisis. Las cifras son ilustrativas. Mide tus tamaños de mensajes, picos de tráfico y objetivos de recuperación antes de dimensionar un clúster.
Describe la carga antes de contar brokers
Anota eventos por segundo en promedio y en picos, tamaño típico y percentiles altos, días de retención, grupos lectores independientes, retraso máximo aceptable y tiempo de recuperación tras perder un consumidor o un broker. Pregunta si los eventos del mismo pedido deben conservar su orden. Normalmente basta con el orden por entidad; un orden total de todos los pedidos forzaría una restricción innecesaria.
Como estimación, 2.000 eventos por segundo de 1 KB son unos 2 MB/s de datos brutos. En siete días, el volumen bruto supera aproximadamente un terabyte. No es una fórmula de almacenamiento: compresión, índices, réplicas, protocolo y ráfagas alteran la cifra. Haz pruebas con datos representativos y deja margen.
Calcula también la capacidad de recuperación. Si un consumidor procesa exactamente al ritmo al que entran nuevos eventos, jamás eliminará el atraso acumulado durante una interrupción. Necesitas una tasa de lectura superior a la de entrada durante la recuperación.
La clave de partición define la promesa de orden
Kafka conserva el orden dentro de cada partición. Usa orderId como clave si todos los eventos del mismo pedido deben llegar al consumidor en orden. customerId establece un orden por cliente, que no es lo mismo. Una clave constante concentra todo en una partición; una clave aleatoria reparte la carga, pero pierde el orden entre eventos relacionados.
Ocho particiones permiten como máximo ocho consumidores activos del mismo grupo para ese tema. No garantizan una distribución equilibrada: una clave muy frecuente puede saturar una partición y dejar otras ociosas. Mide entrada, latencia y lag por partición, además de los promedios del tema.
Aumentar el número de particiones después puede cambiar a qué partición van los eventos futuros de una clave. Si el orden histórico por clave es estricto, prepara una migración controlada, quizá hacia un tema nuevo. Tampoco crees cientos de particiones por rutina; consumen recursos y complican la operación.
Replicación y confirmaciones son una decisión conjunta
El factor de replicación indica cuántas copias mantiene Kafka de una partición. Tres réplicas distribuidas entre dominios de fallo adecuados son una opción habitual, pero la durabilidad real depende también de su ubicación y salud, de acks en el productor y de min.insync.replicas. Evalúa esas opciones como conjunto. acks=all por sí solo no explica toda la garantía que prometes.
Un productor idempotente reduce duplicados debidos a reintentos de publicación en Kafka. No convierte en atómica la transacción de PostgreSQL con la publicación, ni reconoce dos peticiones de negocio independientes como una sola. Las transacciones de Kafka pueden coordinar registros de salida y offsets consumidos en flujos de Kafka a Kafka. Para pagos, correos y escrituras externas necesitas otra estrategia de idempotencia.
Apaga un broker en un entorno de pruebas con una configuración representativa. Comprueba errores de producción, tiempo de recuperación y comportamiento del consumidor. Un Kafka local de un solo broker sirve para aprender, no para demostrar tolerancia a fallos. Kafka 4.x usa KRaft; el modo ZooKeeper se eliminó en Kafka 4.0. Contrasta los tutoriales antiguos con la versión desplegada.
Observa el lag y el tiempo de negocio
El grupo guarda su posición mediante commits de offsets. El lag compara esa posición con el último offset disponible de cada partición. Es una pista valiosa, pero no equivale a minutos de retraso: mil eventos pequeños pueden resolverse enseguida y mil llamadas lentas a una API pueden tardar horas. Mide también la edad del evento pendiente más antiguo y el tiempo desde el evento hasta el efecto de negocio.
| Señal | Posible explicación | Primera comprobación |
|---|---|---|
| Lag en todas las particiones | Entradas superiores a la capacidad o dependencia lenta | Compara tasas de entrada y salida |
| Una partición atrasada | Clave caliente o registro problemático | Identifica clave, offset y error |
| Rebalances frecuentes | Reinicios o procesamiento que retrasa el poll | Revisa membresía y duración de tareas |
| Edad del outbox creciente | Publicación detenida antes de Kafka | Inspecciona el publicador |
| Particiones insuficientemente replicadas | Broker, disco o red degradados | Comprueba salud del clúster |
| Cola de errores creciente | Evento defectuoso o esquema incompatible | Localiza la primera versión fallida |
Vincula las alertas a la tolerancia del negocio. Si inventario debe reservar en dos minutos, mide el tiempo entre orders.placed.v1 y la reserva. Etiqueta paneles con grupo y partición; evita una etiqueta distinta por orderId, que dispararía la cardinalidad.
Rebalances, presión y reejecución segura
Al cambiar la membresía de un grupo pueden reasignarse particiones. Un consumidor no debe asumir que conserva una partición mientras termina un lote en memoria. Consulta las funciones de rebalanceo del cliente, coordina trabajos en curso y confirma offsets solo tras completar el procesamiento. Si el trabajo bloquea durante mucho tiempo el ciclo de lectura, emplea una cola interna acotada con seguimiento cuidadoso de offsets.
Más consumidores ayudan si quedan particiones asignables y el cuello de botella está en el consumidor. Si todos esperan la misma tabla de PostgreSQL o una API externa saturada, añadir consumidores empeora el problema. Limita concurrencia, aplica presión de retorno y considera pausar una partición si el cliente lo permite.
Si el proceso escribe en la base de datos y cae antes de confirmar el offset, el evento se repetirá. Usa un eventId estable y una restricción única o registro de operaciones procesadas. Confirmar primero y escribir después puede perder trabajo al caer. No existe un interruptor universal de “exactly once” para cualquier efecto externo.
Retención, replay y contratos
La retención marca cuánto tiempo permanece un registro, independientemente de que se haya leído. Debe superar las interrupciones previsibles y la ventana de replay prometida, con margen. Cuando un grupo queda detrás del primer offset conservado, Kafka ya no puede servirle ese historial. Alerta antes y define una fuente alternativa si hace falta más historia.
La compactación puede conservar el valor más reciente por clave en temas de estado, pero no es un registro íntegro de auditoría. Reconstruir una tabla de proyección suele ser distinto de volver a cobrar o enviar un correo. Documenta desde qué offset o fecha se relee, con qué grupo, qué efectos se desactivan y cómo se verifica el resultado.
Cada contrato de evento debería declarar dueño, significado, clave, eventId, instante de ocurrencia, versión, campos obligatorios y política de compatibilidad. Un campo añadido puede romper un decodificador estricto. Prueba cambios contra consumidores que pueden ir atrasados. No publiques entidades ORM completas ni secretos. Define quién aprueba cambios de esquema, particiones, retención y permisos.
Seguridad y un plan de incidentes
Cifra el tráfico, autentica clientes y concede permisos mínimos por tema y grupo. Guarda credenciales en un almacén de secretos, rótalas y audita operaciones administrativas. Reduce datos personales en los eventos y evita registrar el cuerpo completo en logs. Separa accesos de desarrollo y producción.
Antes de desplegar, comprueba compatibilidad de esquemas, una prueba de carga representativa y paneles para errores del productor, edad del outbox, lag, rebalances y tiempo hasta el resultado de negocio. Elige explícitamente si un grupo nuevo empieza en earliest o latest. Ensaya una reversión que no cambie silenciosamente el significado de los eventos.
Cuando el lag suba de repente:
- Delimita grupo, tema y particiones. Compara entrada con capacidad de procesamiento.
- Examina despliegues, cambios de esquema, mantenimiento de brokers, dependencias y credenciales.
- Inspecciona el offset y la categoría del error con una muestra que no revele información sensible.
- Protege los sistemas posteriores: reduce concurrencia o pausa la partición si los reintentos amplifican el fallo.
- Corrige código o datos y reanuda o relee con comprobaciones de idempotencia.
- Verifica reservas y otros resultados reales. Un lag descendente por sí solo no prueba que el negocio esté correcto.
Antes de declarar Kafka listo para producción, ensaya pérdida de broker, caída del consumidor, evento defectuoso y replay. La fiabilidad nace de decisiones verificadas sobre identidad, orden, capacidad, efectos externos y recuperación.
Fuentes
Artículos destacados

Laravel y Kafka sin eventos perdidos: outbox transaccional y consumidores idempotentes con PostgreSQL
Una confirmación en PostgreSQL y una publicación en Kafka no forman una transacción ordinaria. Aprende a evitar pérdidas y duplicación de efectos.

Apache Kafka explicado: temas, particiones, grupos de consumidores y tu primer flujo de eventos
Sigue un evento de pedido desde el productor hasta varios consumidores y prueba en local cómo funcionan las particiones, el orden y la reproducción.

Cómo diseñar APIs en las que los clientes puedan confiar: guía práctica desde el contrato
Una buena API hace predecible la próxima acción del cliente. Diseña una inscripción a un curso con reintentos seguros, errores útiles y un plan de evolución.
Comentarios
0 comentariosTodavía no hay comentarios aprobados. Las respuestas nuevas pueden esperar moderación.