Dominando la Configuración de Temas en Kafka: Una Guía Completa

Una guía práctica sobre particiones, replicación, retención, compactación y cambios seguros de configuración en temas de Kafka.

Dominando la Configuración de Temas en Kafka: Una Guía Completa

La configuración de temas en Kafka determina cómo se almacenan, copian, expiran, compactan y consumen tus datos. Puedes ejecutar Kafka con valores predeterminados por un tiempo, especialmente en un clúster de desarrollo, pero los temas de producción requieren más cuidado. Un número incorrecto de particiones puede atrapar una carga de trabajo intensa. Una replicación débil puede convertir una falla de broker en pérdida de datos. Una retención laxa puede llenar los discos. La compactación puede sorprenderte si las claves faltan o son inconsistentes.

La forma útil de abordar la configuración de temas en Kafka no es memorizar cada ajuste. Comienza con las preguntas que un sistema real plantea: ¿cuánto paralelismo necesito?, ¿cuánto tiempo deben estar disponibles los datos?, ¿cuántos datos puedo permitirme almacenar?, ¿qué sucede durante una falla de broker?, y ¿los consumidores necesitan un historial completo de eventos o solo el último valor por clave?

Un tema se divide en particiones. Cada partición es un registro ordenado. Kafka preserva el orden dentro de una partición, no en todo el tema. Si todos los eventos de un cliente deben procesarse en orden, usa una clave estable como customer_id para que esos eventos caigan en la misma partición. Si usas claves aleatorias, puedes obtener una mejor distribución pero perder el orden por entidad.

El número de particiones es una de las primeras decisiones que la gente lamenta. Más particiones permiten más paralelismo de consumidores porque, dentro de un grupo de consumidores, una partición es consumida por solo un miembro del grupo a la vez. Si un tema tiene seis particiones, un grupo de consumidores puede usar activamente hasta seis consumidores para ese tema. Agregar un séptimo consumidor no aumentará el consumo para ese tema a menos que haya otras particiones asignadas.

Más particiones también tienen un costo. Aumentan los metadatos, los archivos abiertos, el trabajo de replicación, el trabajo de elección de líder y el tiempo de recuperación después de fallas de broker. Un número muy alto de particiones puede hacer que las operaciones del clúster sean más lentas incluso si cada partición tiene un tráfico modesto. No hay un número universal mejor. Un tema interno pequeño puede estar bien con tres particiones. Un flujo de eventos ocupado puede necesitar docenas. Una instalación muy grande de Kafka puede usar muchos más, pero eso debe basarse en el rendimiento medido y la capacidad operativa, no en el hábito.

Crea un tema con configuraciones explícitas:

kafka-topics.sh --create   --bootstrap-server broker1:9092   --topic user-events.v1   --partitions 12   --replication-factor 3   --config min.insync.replicas=2

El nombre del tema también debe transmitir cierta intención. Nombres como events o data se vuelven inútiles una vez que el clúster crece. user-events.v1, billing-invoices.v1 o inventory-adjustments.v1 les dice a los futuros operadores qué es el flujo y te da espacio para un cambio de esquema disruptivo más adelante.

El factor de replicación controla cuántas copias Kafka mantiene para cada partición. En producción, 3 es un valor predeterminado común porque permite que un broker falle mientras aún queda otra réplica disponible. No significa que puedas ignorar la configuración del productor. Si los productores usan acks=1, Kafka puede confirmar los registros antes de que los seguidores los hayan copiado. Para temas importantes, combina el factor de replicación tres con min.insync.replicas=2 a nivel de tema y acks=all del productor.

min.insync.replicas a menudo se malinterpreta. No crea réplicas. Indica cuántas réplicas sincronizadas deben estar disponibles para que una escritura con acks=all tenga éxito. Con un factor de replicación de tres y min.insync.replicas=2, el tema puede tolerar que un broker no esté disponible. Si solo queda una réplica sincronizada, Kafka debe rechazar las escrituras fuertes en lugar de aceptar datos con muy pocas copias seguras.

La configuración de retención decide cuándo Kafka puede eliminar segmentos de registro antiguos. La retención basada en tiempo se controla mediante retention.ms a nivel de tema. La retención basada en tamaño se controla mediante retention.bytes. Nombres más antiguos a nivel de broker como log.retention.ms son valores predeterminados del broker; la configuración del tema comúnmente usa retention.ms.

Por ejemplo, para retener un tema durante siete días:

kafka-configs.sh --alter   --bootstrap-server broker1:9092   --entity-type topics   --entity-name user-events.v1   --add-config retention.ms=604800000

Para limitar el almacenamiento por partición, usa retention.bytes:

kafka-configs.sh --alter   --bootstrap-server broker1:9092   --entity-type topics   --entity-name user-events.v1   --add-config retention.bytes=10737418240

Recuerda que retention.bytes generalmente es por partición, no el tamaño total del tema. Un tema con doce particiones y retention.bytes=10GB puede usar aproximadamente 120GB antes de la replicación, y aproximadamente 360GB con un factor de replicación de tres. Este es el tipo de detalle que causa alertas de disco sorpresa.

Kafka elimina datos por segmento de registro, no registro por registro. Si estableces un período de retención corto pero segmentos grandes, la eliminación puede no ocurrir en el minuto exacto que esperas. Configuraciones de segmento como segment.bytes y segment.ms influyen en cuándo Kafka pasa a un nuevo segmento, y solo los segmentos cerrados son elegibles para eliminación o compactación. Segmentos más pequeños pueden hacer que la limpieza sea más receptiva, pero agregan sobrecarga.

cleanup.policy decide qué hace Kafka con los datos antiguos. El valor predeterminado es delete, que elimina segmentos antiguos según la retención. compact mantiene el registro más reciente para cada clave y eventualmente elimina registros más antiguos con la misma clave. También puedes usar delete,compact para temas que necesitan compactación más una ventana de retención.

La compactación es útil para flujos similares a estados: actualizaciones de perfil de usuario, valores de banderas de características, configuraciones de cuenta o eventos de cambio de base de datos con clave primaria. Es una mala opción para un historial de eventos donde cada evento importa. Si compactas un registro de auditoría, los eventos más antiguos para la misma clave pueden desaparecer eventualmente. Eso puede ser exactamente incorrecto para cumplimiento o depuración.

La compactación también depende de las claves. Un tema compactado con claves nulas o inconsistentes no se comportará como un registro de cambios clave-valor limpio. Si los productores envían actualizaciones de usuario a veces con clave user_id y a veces con clave de correo electrónico, Kafka ve claves diferentes. No puede inferir que representan al mismo usuario.

La compresión puede ser establecida por los productores, y un tema puede definir compression.type para controlar el comportamiento del broker. Los valores comunes incluyen producer, gzip, snappy, lz4 y zstd, dependiendo de la versión de Kafka. Muchos equipos dejan el tema en producer y estandarizan la compresión del productor. lz4 y zstd son opciones comunes, pero la respuesta correcta depende del presupuesto de CPU, la forma del mensaje y la presión de la red.

Puedes inspeccionar la configuración del tema así:

kafka-configs.sh --describe   --bootstrap-server broker1:9092   --entity-type topics   --entity-name user-events.v1

E inspeccionar la ubicación de las particiones así:

kafka-topics.sh --describe   --bootstrap-server broker1:9092   --topic user-events.v1

Usa ambos comandos. Las configuraciones del tema te indican retención, compactación y reglas ISR. La descripción del tema te indica líderes, réplicas y estado ISR. Un tema puede tener una configuración perfecta y aún así no estar saludable porque las réplicas están fuera de sincronía.

Algunos cambios son fáciles. La retención, la política de compactación, min.insync.replicas y varias otras configuraciones del tema se pueden alterar dinámicamente. Algunos cambios requieren más precaución. Puedes aumentar el número de particiones, pero no puedes disminuirlo de manera segura con un comando simple. Aumentar las particiones también cambia la distribución de claves para registros futuros porque el cálculo de particionamiento tiene más particiones objetivo. Los registros existentes permanecen donde están; los nuevos registros para la misma clave pueden ir a una partición diferente después del aumento, dependiendo del particionador. Si el orden estricto por clave importa a través del cambio, planifica cuidadosamente.

Los cambios en el factor de replicación son trabajo operativo. Aumentar las réplicas para un tema existente significa que Kafka debe copiar los datos existentes a nuevos brokers. Eso puede ser mucha E/S. Usa herramientas de reasignación, monitorea el progreso y limita si es necesario. No inicies una reasignación grande durante el tráfico pico a menos que ya sepas que el clúster tiene suficiente capacidad de repuesto.

Para un tema de eventos de producción normal, un punto de partida práctico podría verse así:

kafka-topics.sh --create   --bootstrap-server broker1:9092   --topic payments-authorized.v1   --partitions 24   --replication-factor 3   --config min.insync.replicas=2   --config retention.ms=1209600000   --config cleanup.policy=delete

Eso dice: suficientes particiones para paralelismo, tres copias para disponibilidad, dos réplicas sincronizadas requeridas para escrituras fuertes, catorce días de retención y sin compactación porque cada evento de autorización de pago importa.

Para un tema de estado, la forma es diferente:

kafka-topics.sh --create   --bootstrap-server broker1:9092   --topic user-preferences.v1   --partitions 12   --replication-factor 3   --config min.insync.replicas=2   --config cleanup.policy=compact

Ese tema debe tener clave por ID de usuario. Los consumidores que reconstruyen el estado pueden leer el registro compactado y eventualmente ver el último valor para cada usuario. No deben esperar que cada cambio de preferencia histórico permanezca para siempre.

La mejor configuración de tema es aburrida de operar. Tiene suficientes particiones pero no miles sin razón. Tiene replicación que coincide con el valor de los datos. Tiene retención que coincide con las necesidades de recuperación y cumplimiento. Usa compactación solo cuando las claves son significativas. Está descrita en código o documentación para que otro ingeniero pueda recrearla sin adivinar.

Un hábito de revisión útil es escribir la historia del consumidor antes de elegir la configuración del tema. ¿Quién lee este tema? ¿Necesitan reproducir desde el principio? ¿Cuánto tiempo tomaría una reconstrucción completa? ¿Puede el sistema fuente volver a publicar datos antiguos? Si un consumidor está inactivo durante tres días, ¿Kafka debería tener aún los registros perdidos? Esas respuestas impulsan la retención de manera más honesta que una configuración predeterminada de siete días.

Considera un consumidor de detección de fraude que lee eventos de pago. Si está inactivo durante seis horas, casi con certeza querrás que se ponga al día desde Kafka. Si está inactivo durante treinta días, puedes esperar un proceso de relleno separado desde la base de datos de pagos. Ese tema podría necesitar dos semanas de retención, no para siempre. Un tema de auditoría de seguridad puede tener un requisito diferente, quizás enviar a almacenamiento de objetos para retención a largo plazo mientras Kafka mantiene solo la ventana de reproducción activa.

El tamaño del mensaje también pertenece a la conversación del tema. Kafka puede manejar registros más grandes cuando está configurado para ello, pero los mensajes grandes afectan a los productores, brokers, consumidores, replicación y memoria de búsqueda. Si los equipos comienzan a poner blobs JSON de varios megabytes o archivos codificados en un tema, no solo aumentes max.message.bytes y sigas adelante. Pregunta si la carga útil pertenece al almacenamiento de objetos con una referencia en Kafka. Kafka generalmente es mejor moviendo eventos, no actuando como un almacén de blobs.

La evolución del esquema no es una configuración del tema, pero da forma al diseño del tema. Un tema nombrado con un sufijo de versión, como orders.v1, te da una salida de emergencia cuando un cambio disruptivo es inevitable. Los cambios compatibles pueden permanecer en el mismo tema si los consumidores y productores siguen una política de esquema. Los cambios disruptivos no deben deslizarse en el mismo tema porque un equipo controla el productor. Kafka desacopla sistemas, pero solo si se respeta el contrato.

Finalmente, documenta la propiedad del tema. Cada tema de producción debe tener un equipo propietario, productores esperados, consumidores esperados, razón de retención y notas de sensibilidad de datos. Esto suena administrativo hasta que el disco se llena a las 02:00 y nadie sabe si un tema puede acortarse, eliminarse, compactarse o limitarse. Una buena configuración de tema es en parte técnica y en parte memoria operativa.

Una verificación final antes de publicar un tema es ejecutar un escenario de falla. Si un broker desaparece, ¿los productores aún pueden escribir? Si un grupo de consumidores está inactivo durante el fin de semana, ¿la retención cubrirá la brecha? Si un productor envía datos incorrectos, ¿los consumidores pueden saltar, poner en cuarentena o reproducir de manera segura? Si el tema crece el doble de rápido de lo esperado, ¿qué límite protege el clúster: tiempo de retención, bytes de retención, cuotas o una alerta?

Vale la pena mencionar las cuotas porque la configuración del tema por sí sola no protege un clúster compartido de un productor ruidoso. Kafka admite cuotas de cliente que pueden limitar las tasas de producción y búsqueda. Si varios equipos comparten un clúster, las cuotas pueden evitar que una reproducción accidental o un productor descontrolado abrumen a los brokers. Deben combinarse con alertas para que los equipos sepan que están siendo limitados en lugar de culpar silenciosamente a Kafka.

No olvides la política de eliminación. Algunos clústeres deshabilitan la eliminación de temas a nivel de broker para prevenir accidentes. Eso puede ser sensato, pero significa que los temas abandonados deben manejarse a través de un proceso de limpieza controlado. Una revisión del inventario de temas cada mes o trimestre puede recuperar una cantidad sorprendente de disco, especialmente en clústeres de desarrollo y pruebas donde los experimentos dejan temas antiguos.