Nivel 3 · 30 min
Kafka Avanzado
Kafka avanzado cubre la semántica exactly-once (EOS), productores idempotentes, transacciones y compactación de log. Estas funcionalidades habilitan a Kafka para usarse como backbone de mensajería transaccional — no solo un bus best-effort.
Semántica Exactly-Once
La semántica exactly-once (EOS) significa que cada mensaje se procesa exactamente una vez — sin duplicados ni pérdidas. Lograr EOS requiere tres componentes trabajando juntos: (1) productores idempotentes para prevenir duplicados de reintentos, (2) transacciones Kafka para writes atómicos multi-partición, y (3) consumidores leyendo solo mensajes commiteados (isolation.level=read_committed). El patrón read-process-write con transacciones: consumir del topic de entrada, procesar, escribir al topic de salida y commitear offsets de entrada atómicamente en una transacción.
Productores Idempotentes y Transacciones
Productor idempotente (enable.idempotence=true): cada mensaje recibe un número de secuencia. El broker deduplica reintentos — aunque el productor reenvíe en caso de falla de red, el broker almacena solo una copia. Transacciones Kafka (transactional.id): un productor puede escribir a múltiples particiones/topics atómicamente. O todos los writes tienen éxito (commiteados) y se vuelven visibles a consumidores read_committed, o todos se abortan. beginTransaction() → send() → sendOffsetsToTransaction() → commitTransaction(). Se usa en Kafka Streams para procesamiento EOS.
Compactación de Log
La compactación de log mantiene el último valor para cada clave — en lugar de eliminar registros viejos por tiempo, retiene el registro más reciente por clave. Tombstone: enviar un registro con valor null marca la clave para eliminación en la próxima compactación. Casos de uso: changelog topics (último estado de una entidad), snapshots de tabla de DB, stores de configuración. Compactación vs retención: retención elimina por tiempo/tamaño; compactación elimina por claves supersedidas. Un topic compactado puede reproducirse para reconstruir el estado actual de todas las claves.
Code example
// Exactly-once: read-process-write atómico
producer.initTransactions();
try {
producer.beginTransaction();
ConsumerRecords<K,V> records = consumer.poll(...);
List<ProducerRecord<K,V>'> outputs = process(records);
outputs.forEach(producer::send);
Map<TopicPartition, OffsetAndMetadata> offsets = currentOffsets(records);
producer.sendOffsetsToTransaction(offsets, consumer.groupMetadata());
producer.commitTransaction();
} catch (Exception e) {
producer.abortTransaction();
}