📖 Scenario: You are working with a Kafka stream that processes orders. You want to ensure that each order is processed exactly once to avoid duplicates or missing data.
🎯 Goal: Build a simple Kafka Streams application that reads from an input topic, processes the data with exactly-once semantics enabled, and writes to an output topic.
📋 What You'll Learn
Create a Kafka Streams configuration with exactly-once processing enabled
Define input and output topics named orders-input and orders-output
Implement a simple stream processing topology that reads from orders-input and writes to orders-output
Print the final topology description to verify the setup
💡 Why This Matters
🌍 Real World
Exactly-once processing is critical in financial transactions, order processing, and inventory management to avoid duplicates or data loss.
💼 Career
Many companies require engineers to build reliable stream processing pipelines with Kafka that guarantee data consistency and fault tolerance.
Progress0 / 4 steps
1
Create Kafka Streams configuration
Create a Properties object called props and set the following properties exactly: APPLICATION_ID_CONFIG to "exactly-once-app", BOOTSTRAP_SERVERS_CONFIG to "localhost:9092", and PROCESSING_GUARANTEE_CONFIG to StreamsConfig.EXACTLY_ONCE_V2.
Kafka
Hint
Use props.put to set each configuration property exactly as specified.
2
Define input and output topics
Create two String variables named inputTopic and outputTopic and assign them the exact values "orders-input" and "orders-output" respectively.
Kafka
Hint
Declare two string variables with the exact topic names.
3
Build the Kafka Streams topology
Create a StreamsBuilder object called builder. Use it to create a KStream<String, String> named stream that reads from inputTopic. Then write this stream to outputTopic using the to() method.
Kafka
Hint
Use builder.stream() to read and stream.to() to write.
4
Print the topology description
Create a KafkaStreams object called streams using builder.build() and props. Then print the topology description by calling streams.toString() inside a System.out.println().
Kafka
Hint
Create the KafkaStreams object and print its topology description.
Practice
(1/5)
1. What is the main benefit of exactly-once stream processing in Kafka?
easy
A. It ensures messages are processed only once, avoiding duplicates.
B. It speeds up message delivery by skipping acknowledgments.
C. It allows messages to be processed multiple times for safety.
D. It disables message ordering to improve throughput.
Solution
Step 1: Understand exactly-once processing goal
Exactly-once processing means each message affects the system only once, preventing duplicates.
Step 2: Compare options with this goal
Only It ensures messages are processed only once, avoiding duplicates. describes avoiding duplicates by processing messages once.
Final Answer:
It ensures messages are processed only once, avoiding duplicates. -> Option A
Quick Check:
Exactly-once = no duplicates [OK]
Hint: Exactly-once means no duplicate effects on data [OK]
Common Mistakes:
Confusing exactly-once with at-least-once processing
Thinking it speeds up delivery by skipping steps
Assuming it allows multiple processing for safety
2. Which Kafka producer configuration enables exactly-once semantics?
easy
A. compression.type = none
B. enable.idempotence = true
C. acks = 0
D. max.in.flight.requests.per.connection = 10
Solution
Step 1: Identify config for exactly-once
Enabling idempotence ensures the producer can retry without duplicates.
Step 2: Match config options
Only 'enable.idempotence = true' enables this feature.
Final Answer:
enable.idempotence = true -> Option B
Quick Check:
Idempotence enabled = exactly-once [OK]
Hint: Idempotence true enables exactly-once in Kafka producer [OK]
Common Mistakes:
Choosing acks=0 which disables acknowledgments
Confusing compression with processing guarantees
Setting max.in.flight.requests without idempotence
3. Given this Kafka Streams code snippet, what is the output if a failure occurs before commit?
B. Processed record may be duplicated after restart.
C. Processed record is committed exactly once.
D. Processed record is lost and not committed.
Solution
Step 1: Analyze transaction handling
If an exception occurs before commit, abortTransaction() is called, rolling back changes.
Step 2: Determine output effect
Rollback means the processed record is not committed and effectively lost in this run.
Final Answer:
Processed record is lost and not committed. -> Option D
Quick Check:
Abort transaction = no commit = lost record [OK]
Hint: Abort transaction means no commit, so data is lost [OK]
Common Mistakes:
Assuming record is committed despite failure
Thinking abortTransaction duplicates records
Confusing commitTransaction with abortTransaction
4. Identify the error in this Kafka Streams code snippet for exactly-once processing:
props.put("enable.idempotence", "true");
props.put("transactional.id", "txn-1");
KafkaProducer producer = new KafkaProducer(props);
producer.beginTransaction();
producer.send(record);
// Missing commit or abort here
producer.close();
medium
A. Missing commitTransaction or abortTransaction before close.
B. enable.idempotence should be false for transactions.
C. transactional.id must be unique per message.
D. KafkaProducer cannot be closed after sending messages.
Solution
Step 1: Review transaction lifecycle
After beginTransaction and send, a commit or abort must finalize the transaction.
Step 2: Identify missing step
The code closes producer without committing or aborting, causing incomplete transaction.
Final Answer:
Missing commitTransaction or abortTransaction before close. -> Option A
Quick Check:
Transactions need commit or abort before close [OK]
Hint: Always commit or abort before closing producer [OK]
Common Mistakes:
Thinking idempotence false is needed for transactions
Believing transactional.id changes per message
Assuming producer close auto-commits transactions
5. You want to build a Kafka Streams application that updates user balances exactly once, even if failures occur. Which approach ensures this behavior?
hard
A. Process messages without committing offsets to avoid duplicates.
B. Disable transactions and rely on at-least-once processing with retries.
C. Use idempotent producer with transactions and commit offsets atomically.
D. Use multiple producers without transactions to increase throughput.
Solution
Step 1: Understand exactly-once requirements
Exactly-once needs atomic commit of data and offsets to avoid duplicates or loss.
Step 2: Match approach to requirements
Using idempotent producer with transactions and atomic offset commits ensures exactly-once updates.
Final Answer:
Use idempotent producer with transactions and commit offsets atomically. -> Option C