Apache Spark
Kafka
Batch Processing
Data Streaming
Offset Tracking

Spark batch reading from Kafka & using Kafka to keep track of offsets

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Apache Spark is a powerful, unified analytics engine for large-scale data processing and analysis, which interacts seamlessly with Apache Kafka, a distributed streaming platform capable of handling trillions of events a day. Integrating Spark with Kafka offers robust solutions for processing streams of data in real time or batch modes. Specifically, this article focuses on how to perform batch reading from Kafka using Spark and how to manage Kafka offsets within Spark to ensure that no data is lost or processed twice.

Understanding Kafka Offsets

In Kafka, an offset is a unique identifier for each record in a partition. It denotes the position of each record within the partition. Kafka maintains the sequential order of records in the form of offsets, which is critical for consumers like Spark to track which records have been consumed and where to start the next read.

Spark's Kafka Integration

To begin batch processing from Kafka in Spark, the first step involves establishing a connection to Kafka. Spark provides a direct approach to stream data from Kafka using Spark Structured Streaming or Spark Streaming. However, when dealing with batch processing, the Spark session reads from Kafka in specific offset ranges for defined topics.

Configuring Kafka with Spark

To configure the connection, use the read API from Spark's Dataframe Reader, setting options for the Kafka parameters. Here is an example in Scala:

scala
1val spark = SparkSession.builder()
2  .appName("KafkaBatchRead")
3  .getOrCreate()
4
5val df = spark
6  .read
7  .format("kafka")
8  .option("kafka.bootstrap.servers", "host1:port1,host2:port2")
9  .option("subscribe", "topic1")
10  .option("startingOffsets", "earliest") // or use specific offsets JSON "{topic:{partition:offset}}"
11  .option("endingOffsets", "latest")
12  .load()

This configuration allows Spark to read data from Kafka topic topic1 from the earliest to the latest offset.

Tracking and Storing Offsets

Tracking offsets when performing batch reads is crucial for data integrity and fault tolerance. Spark allows managing offsets in multiple ways:

  1. Manual Offset Management: After processing the data, manually store the offsets in an external store such as a database or a distributed file system. This method provides flexibility but requires additional code to manage offsets.
  2. Checkpointing: Spark Structured Streaming supports checkpointing, where offsets and other relevant states are saved automatically. This is advantageous for ensuring that no data is lost or duplicated in the event of a failure.

Example of Managing Offsets Manually

After processing the data, you might choose to store the offsets. Here’s a simple example of how one could do that:

scala
1val processedOffsets = df
2  .selectExpr("CAST(partition AS INT)", "CAST(offset AS LONG)")
3  .groupBy("partition")
4  .agg(max("offset").as("offset"))
5  .collect()
6  .map(row => (row.getInt(0), row.getLong(1) + 1))
7  .toMap
8
9// Store `processedOffsets` map to an external storage system

Benefits and Challenges

Integrating Kafka with Spark for batch reading has several benefits, including the ability to handle large data volumes efficiently, high throughput, and the durability of Kafka combined with the fast processing power of Spark. However, the setup can be complex, especially when ensuring exactly-once semantics for offset tracking.

Key ComponentDescriptionExample
Kafka OffsetUnique identifier of records within a partition.42 (represents the 43rd record)
Spark DataframeUsed to load and process Kafka data in batches.spark.read.format("kafka")...load()
Offset ManagementEnsuring no data loss or duplication during processing.Manual, Checkpointing

Conclusion

Batch reading from Kafka using Apache Spark provides efficient and powerful data processing capabilities. Proper management of Kafka offsets during batch processing is essential to maintain data consistency and ensure fault tolerance. By carefully managing the configurations and understanding the interplay between Kafka and Spark, developers can build robust batch processing applications that effectively handle large-scale data streams.


Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.