In this lesson, you will learn how to achieve "Exactly Once" processing semantics to ensure that your data remains consistent and accurate even when your stream processing applications crash or restart.
The Challenge of Duplicates
In a distributed streaming system, a failure often occurs right after an event is processed but before the system can acknowledge it. When the system recovers, it might re-process the same event, leading to duplicates. "Exactly Once" semantics guarantees that even if a message is processed multiple times due to retries or failures, the downstream state or output reflects the effect of that message only once.
The Mechanism: Atomic Transactions
To achieve this, we rely on atomic transactions. Think of it as a "read-process-write" cycle that is bound together. In Kafka, this is implemented through the Transactional API. When your stream processor consumes an offset, performs a transformation, and produces a result to a new topic, all three actions—committing the input offset, writing the result, and updating the state—must succeed together or fail together.
Consider this conceptual flow:
- Begin Transaction: The processor initiates a transaction session.
- Read-Process-Write: The application consumes an input record, calculates a new value, and writes it to the output topic.
- Commit Offsets: The input topic offset is committed as part of the transaction.
- Finalize: The application commits the transaction. If any part fails, the transaction is aborted, and the output is never visible to consumers.
// Conceptual transactional write
producer.beginTransaction();
try {
producer.send(record);
producer.sendOffsetsToTransaction(offsets, consumerGroupId);
producer.commitTransaction();
} catch (ProducerFencedException | OutOfOrderSequenceException | AuthorizationException e) {
producer.abortTransaction();
}
Why it Matters
Without these semantics, downstream systems (like a database or a dashboard) might show double-counted transactions or incorrect totals. By using transactions, you ensure that the state of your application and the logs in your Kafka topics remain perfectly synchronized, regardless of broker rebalances or network flickers.
Key Takeaway: Exactly Once semantics relies on atomic transactions to group the consumption of offsets and the production of results, ensuring that internal state and output data remain consistent despite system failures.