Kafka Consumer
CommitSync
CommitAsync
Data Processing
Stream Processing

Kafka-consumer. commitSync vs commitAsync

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Apache Kafka is a widely used system for managing real-time data feeds. Kafka’s ability to handle high throughput makes it suited for scenarios like tracking activity streams, collecting logs, and managing IoT data sources. One significant aspect of Kafka is its consumer implementation which allows applications to read data from Kafka topics. In Kafka, the process of consuming messages includes not only fetching the messages but also managing the consumer’s offset, which points to the last message that has been consumed. Managing this offset can be done synchronously or asynchronously, which are crucial concepts to understand for maintaining data consistency and improving application throughput.

Understanding Kafka Consumer Offsets

In Kafka, every message in a partition has a sequential ID number called the offset that uniquely identifies each message. Consumers use this offset to keep track of which messages have been processed. When a consumer reads messages, it should periodically save the offsets of messages it has already consumed. This way, if the consumer needs to restart, it can begin consuming from where it left off. This process of saving the offset is known as committing the offset.

CommitSync vs CommitAsync

Kafka provides two methods to commit offsets – commitSync and commitAsync. Both methods are used to ensure that the Kafka consumer does not lose its place and can handle restarts gracefully.

commitSync()

The commitSync() method commits the last offset of messages returned by poll() and blocks until either the offset commit is successful or an unrecoverable error is encountered. Since it waits for the broker’s acknowledgment, any failure will throw an exception, and the user can handle this exception to act accordingly (e.g., retrying). This method guarantees reliability because it makes sure that the consumer’s position is safely recorded before proceeding to consume any further messages. However, the synchronous nature of the commit can lead to increased latency in message processing since no new messages will be processed while the commit is in progress.

Example Code:

java
1try {
2    while (true) {
3        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
4        for (ConsumerRecord<String, String> record : records) {
5            processRecord(record);
6        }
7        consumer.commitSync();
8    }
9} catch (Exception e) {
10    log.error("Commit failed", e);
11} finally {
12    consumer.close();
13}

commitAsync()

Alternatively, commitAsync() commits offsets like commitSync() but does it asynchronously. It does not block the consumer and allows it to continue polling more messages while the commit operation is handled in the background. This non-blocking behavior enhances throughput and efficiency, especially in high-load environments. However, since it doesn’t wait for a response from Kafka, handling errors like failed commits becomes tricky. One strategy is to preserve a callback that logs commit errors.

Example Code:

java
1consumer.poll(Duration.ofMillis(100)).forEach(record -> processRecord(record));
2consumer.commitAsync((offsets, exception) -> {
3    if (exception != null) {
4        log.error("Commit failed for offsets {}", offsets, exception);
5    }
6});

Comparing Both Techniques

Here is a brief table summarizing the differences between commitSync() and commitAsync():

FeaturecommitSync()commitAsync()
BlockingYes, it blocks until the commit completes.No, it allows continued processing.
Error HandlingErrors are thrown directly.Errors need to be handled in a callback.
ReliabilityHigher, due to synchronous commit.Lower, commit might fail silently.
ThroughputLower, due to blocking nature.Higher, as it does not block processing.
Use CaseSafety-critical applications.High-throughput applications where occasional loss is acceptable.

Conclusion

Choosing between commitSync and commitAsync largely depends on the specific needs and constraints of your application. If you need high reliability and can trade off some throughput, commitSync is more suitable. On the other hand, if the application demands higher throughput and can tolerate some degree of failure or loss, then commitAsync may be appropriate. In practice, some applications use a combination of both methods — employing asynchronous commits usually, with periodic synchronous commits to minimize the risk of data loss.


Course illustration
Course illustration

All Rights Reserved.