Configuración de Replicación en Kafka: Garantizando Durabilidad y Disponibilidad de Datos
Configure la replicación de Kafka, ISR, acuses de recibo del productor y conciencia de rack sin debilitar la durabilidad.
Configuración de Replicación en Kafka: Garantizando Durabilidad y Disponibilidad de Datos
La configuración de replicación de Kafka es donde un clúster deja de ser un montón de brokers y comienza a comportarse como un sistema en el que se puede confiar durante fallos. Los ajustes no son complicados por sí solos: factor de replicación, réplicas en sincronía, acuses de recibo del productor, elección de líder y ubicación en racks. La parte complicada es que solo tienen sentido juntos.
Un tema con tres réplicas aún puede perder datos confirmados si los productores utilizan acuses de recibo débiles. Un productor que usa acks=all aún puede fallar en escrituras si min.insync.replicas es demasiado estricto para el número de brokers actualmente activos. Un clúster distribuido en zonas de disponibilidad aún puede tener un mal día si todas las réplicas de una partición caliente terminan en el mismo dominio de fallo. La replicación no es una casilla única.
La forma en que me gusta pensar en la replicación de Kafka es simple: para cada partición, Kafka mantiene varias copias, elige una copia para aceptar lecturas y escrituras, y mantiene las otras copias lo suficientemente cerca para que una de ellas pueda asumir el control. Tu trabajo es decidir cuántas copias son suficientes, cuántas deben estar al día antes de que una escritura se considere exitosa, y si el clúster debe preferir la disponibilidad sobre la seguridad de los datos.
Un tema de Kafka se divide en particiones. Cada partición tiene una réplica líder y cero o más réplicas seguidoras. Los productores escriben en el líder. Los consumidores normalmente leen del líder. Las seguidoras obtienen registros del líder y mantienen sus registros locales alineados. Si el broker del líder falla, Kafka elige un nuevo líder entre las réplicas que se consideran candidatas seguras.
Esa lista de candidatas seguras es el ISR, abreviatura de réplicas en sincronía. Una réplica está en el ISR cuando se mantiene al día con el líder lo suficientemente cerca según las reglas de retraso de réplicas de Kafka. Si una seguidora deja de obtener datos, se retrasa demasiado o el broker desaparece, Kafka la elimina del ISR. Cuando se pone al día, puede reincorporarse.
Este detalle importa porque el ISR es lo que hace que la durabilidad de Kafka sea más que un deseo. Con acks=all, el líder no confirma una solicitud de producción hasta que el registro se haya replicado en las réplicas en sincronía requeridas. El requisito exacto está controlado por min.insync.replicas. Si el tema tiene replication.factor=3 y min.insync.replicas=2, Kafka requiere al menos dos réplicas en sincronía antes de que una escritura con acks=all pueda tener éxito.
Esa combinación es común en producción porque proporciona un equilibrio práctico. Un broker puede fallar y el tema aún puede aceptar escrituras fuertemente confirmadas. Si un segundo broker falla antes de que el primero regrese, los productores que usan acks=all deberían comenzar a ver errores como NotEnoughReplicas o NotEnoughReplicasAfterAppend. Eso es molesto durante un incidente, pero suele ser el comportamiento correcto. Kafka se niega a fingir que una escritura es duradera cuando no hay suficientes copias seguras.
Aquí está la línea base de producción típica para un clúster normal de tres o más brokers:
default.replication.factor=3
min.insync.replicas=2
unclean.leader.election.enable=false
Esos valores no hacen que cada carga de trabajo sea segura automáticamente, pero te dan un punto de partida sensato. default.replication.factor=3 significa que los nuevos temas obtienen tres copias a menos que el comando de creación del tema indique lo contrario. min.insync.replicas=2 significa que al menos dos réplicas deben estar en sincronía para escrituras fuertes. unclean.leader.election.enable=false le dice a Kafka que no elija una réplica desactualizada como líder solo para mantener una partición escribible.
No establezcas el factor de replicación más alto que el número de brokers. Kafka no puede colocar tres réplicas en tres brokers diferentes si solo existen dos brokers. En clústeres de desarrollo pequeños, replication.factor=1 está bien porque la conveniencia importa más que la tolerancia a fallos. En producción, 1 significa que la pérdida de un solo broker puede hacer que los datos no estén disponibles y puede perder permanentemente registros almacenados solo en ese broker.
El lado del productor debe coincidir con el lado del tema. Para datos importantes, usa acks=all. También habilita la idempotencia a menos que tengas una razón específica para no hacerlo. En los clientes modernos de Kafka, los productores idempotentes son la opción normal para reducir duplicados causados por reintentos.
acks=all
enable.idempotence=true
retries=2147483647
max.in.flight.requests.per.connection=5
No copies el valor de reintentos ciegamente en cada cliente sin entender tu versión de cliente y requisitos de entrega. La idea importante es que la producción duradera de Kafka generalmente necesita reintentos, idempotencia y acks=all juntos. Si configuras acks=1, el líder puede confirmar un registro antes de que las seguidoras lo hayan copiado. Si ese líder muere en el momento equivocado, un registro confirmado puede desaparecer. Eso es aceptable para algunos flujos de telemetría. No es aceptable para pagos, pistas de auditoría, movimientos de inventario o cualquier cosa que un equipo descendente trate como fuente de verdad.
Cuando crees un tema, establece las opciones de replicación deliberadamente en lugar de confiar en los valores predeterminados del broker que estén presentes:
kafka-topics.sh --create --bootstrap-server broker1:9092 --topic orders.v1 --partitions 12 --replication-factor 3 --config min.insync.replicas=2
El número de particiones es independiente de la replicación. Doce particiones con factor de replicación tres significa treinta y seis réplicas de partición en total. Eso tiene costos de almacenamiento, red, manejadores de archivos y metadatos del controlador. La replicación mejora la durabilidad, pero no es gratuita.
Para temas existentes, cambiar min.insync.replicas es sencillo:
kafka-configs.sh --alter --bootstrap-server broker1:9092 --entity-type topics --entity-name orders.v1 --add-config min.insync.replicas=2
Cambiar el factor de replicación para un tema existente depende de la versión de Kafka y las herramientas. Las versiones más recientes de Kafka admiten kafka-reassign-partitions.sh y, en algunos casos, flujos de trabajo de alteración de temas que facilitan los aumentos. En clústeres más antiguos, aumentar la replicación generalmente significa generar y ejecutar un plan de reasignación de particiones. Disminuir la replicación es más sensible porque estás eliminando copias. Trátalo como una operación planificada, no como un comando casual escrito durante un incidente ruidoso.
Una reasignación debe ser limitada si el tema es grande o el clúster ya está ocupado. La puesta al día de la replicación lee datos antiguos de las réplicas existentes y los escribe en las nuevas. Eso puede robar capacidad de disco y red de los productores y consumidores en vivo. Un runbook seguro generalmente incluye una ventana de mantenimiento, salida --describe antes y después, límites de reasignación y un plan de reversión.
Puedes inspeccionar un tema así:
kafka-topics.sh --describe --bootstrap-server broker1:9092 --topic orders.v1
Mira tres campos en la salida: Leader, Replicas e Isr. Replicas es el conjunto asignado. Isr es el conjunto actualmente al día. Si Replicas es 1,2,3 pero Isr es 1,2, el broker 3 está atrasado o no disponible para esa partición. Si muchas particiones muestran un broker faltante en ISR, revisa el disco, la red, la salud del proceso y los registros de ese broker. Si solo unas pocas particiones calientes están afectadas, el líder puede estar sobrecargado o la partición puede tener tráfico inusualmente alto.
La elección de líder no limpia merece cuidado especial. Si todas las réplicas en sincronía para una partición han desaparecido, Kafka tiene dos opciones. Puede dejar la partición no disponible hasta que una réplica segura regrese, o puede elegir una réplica desincronizada y arriesgarse a perder registros que fueron confirmados en el líder anterior. unclean.leader.election.enable=false elige seguridad. true elige disponibilidad a riesgo de pérdida de datos.
Hay cargas de trabajo donde la elección no limpia puede ser defendible: datos de clics de corta duración, métricas desechables, o un pipeline donde los sistemas ascendentes pueden reproducir todo. Para la mayoría de los datos comerciales, déjalo deshabilitado. Perder disponibilidad para una partición es doloroso, pero la pérdida silenciosa de datos es peor porque los consumidores pueden continuar como si nada hubiera pasado.
La replicación consciente de racks ayuda con una clase diferente de fallo. Si tus brokers están divididos en racks, zonas o hosts con rutas de alimentación/red compartidas, dile a Kafka dónde vive cada broker:
broker.rack=zone-a
Establece el valor correcto en cada broker. Kafka intentará distribuir las réplicas entre los racks para que un solo fallo de zona sea menos probable que elimine cada copia de una partición. Esto no es magia. Aún necesitas suficientes brokers en cada zona, suficiente disco y una colocación cuidadosa de las particiones. Pero sin broker.rack, Kafka no tiene forma de saber que dos brokers comparten el mismo dominio de fallo.
Monitorea la replicación continuamente. Las señales de advertencia temprana más útiles son particiones sub-replicadas, particiones fuera de línea, eventos de reducción de ISR y errores de producción relacionados con réplicas insuficientes. En configuraciones basadas en Prometheus, los equipos comúnmente observan métricas de brokers de Kafka para particiones sub-replicadas y fuera de línea, luego combinan esas alertas con métricas de disco, red y JVM del broker.
Una buena pregunta de incidente es: ¿el ISR se redujo porque un broker murió, porque la replicación no puede mantenerse al día, o porque la red no es confiable? La solución difiere. Un broker muerto necesita recuperación del servicio. Un broker lento puede necesitar reemplazo de disco, investigación de E/S o menos líderes de partición. Un problema de red puede manifestarse como desconexiones repetidas y retraso del buscador incluso cuando la CPU y el disco se ven bien.
Los reinicios rodantes de brokers son otro lugar donde los ajustes de replicación muestran su valor. Reinicia un broker a la vez. Espera a que las particiones recuperen un ISR saludable antes de reiniciar el siguiente broker. Si reinicias los brokers demasiado rápido con min.insync.replicas=2, los productores pueden comenzar a fallar porque hay demasiadas pocas réplicas en sincronía. Ese fallo es esperado, pero puedes evitarlo con paciencia y monitoreo.
La lista de verificación práctica es corta. Usa factor de replicación tres para la mayoría de los temas de producción. Usa min.insync.replicas=2 con el productor acks=all para datos importantes. Mantén la elección de líder no limpia deshabilitada a menos que los datos sean explícitamente desechables. Distribuye las réplicas entre dominios de fallo con conciencia de rack. Observa la salud del ISR, no solo el tiempo de actividad del broker. Y prueba tus suposiciones reiniciando un broker en una ventana controlada antes de que una interrupción real lo haga por ti.
Un detalle que ayuda durante las revisiones es separar la durabilidad de la disponibilidad en lenguaje sencillo. La durabilidad pregunta: "Después de que Kafka dice que la escritura tuvo éxito, ¿cuántos fallos pueden ocurrir antes de que ese registro confirmado esté en riesgo?" La disponibilidad pregunta: "¿Pueden los productores y consumidores usar la partición ahora mismo?" Los ajustes fuertes a veces reducen la disponibilidad porque Kafka rechazará escrituras en lugar de aceptar datos débilmente replicados. Eso no es un fallo de Kafka. Eso es Kafka honrando el contrato que configuraste.
Por ejemplo, imagina un tema con factor de replicación tres, min.insync.replicas=2 y productores usando acks=all. El broker 1 es líder, los brokers 2 y 3 son seguidores. Si el broker 3 se cae, el ISR se convierte en 1,2. Las escrituras aún tienen éxito porque dos réplicas están en sincronía. Si el broker 2 se cae antes de que el broker 3 regrese, el ISR se convierte solo en 1. Las escrituras fallan. Algunos equipos ven esto por primera vez en producción y preguntan por qué Kafka está caído cuando el líder aún está vivo. La respuesta es que el tema aún está disponible para algunas lecturas, pero no es seguro para escrituras fuertemente confirmadas.
También deberías pensar en la recuperación del consumidor. La replicación protege las copias de los registros en el lado del broker. No protege automáticamente los offsets del consumidor de cada error de flujo de trabajo. Los offsets del consumidor también se almacenan en Kafka, generalmente en __consumer_offsets, por lo que ese tema interno también necesita una replicación saludable. Si los temas de usuario están cuidadosamente configurados pero los temas internos se crearon con replicación débil en una construcción temprana del clúster, el comportamiento de conmutación por error aún puede ser peor de lo esperado. Verifica la replicación de temas internos como parte de una revisión de preparación para producción.
En clústeres multiinquilino, no todos los temas merecen la misma configuración. Un tema de métricas desechable con alto volumen y bajo valor comercial puede usar una retención más corta y tolerar garantías más débiles. Un tema de facturación no debería. El error es dejar que los valores predeterminados accidentales decidan esa distinción. Pon las clases de temas por escrito: flujos de eventos críticos, telemetría reproducible, temas de estado compactados, temas de desarrollo temporales. Luego asigna cada clase a configuraciones de replicación, ISR, retención y productor.
Durante incidentes, evita cambiar los ajustes de durabilidad solo para silenciar errores a menos que todos entiendan la compensación. Reducir min.insync.replicas de 2 a 1 puede hacer que los productores se muevan, pero también significa que las escrituras confirmadas pueden vivir en un solo broker. Habilitar la elección de líder no limpia puede restaurar la disponibilidad de la partición, pero las réplicas desactualizadas pueden perder registros. A veces el negocio puede elegir esa compensación. Debe ser una decisión consciente del incidente, no un atajo oculto del operador.