Apache Kafka
Spark Streaming
Data Processing
Big Data
Consumer API

Kafka consumer in Spark Streaming

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 Streaming is a powerful tool for performing real-time data processing. Kafka, on the other hand, is a distributed streaming platform that lets you publish and subscribe to streams of records. When integrated, Kafka and Spark Streaming can process data in real-time, making this combination widely popular for real-time analytics.

Kafka Consumer in Spark Streaming

In Spark Streaming, Kafka consumers are used for pulling data streams from Kafka topics. Spark provides two main approaches to consume data from Kafka:

  1. Receiver-based Approach (Spark Streaming + Kafka Integration guide, version 1.3 to 2.2)
  2. Direct Approach (No receivers) (from version 1.3 onwards)

1. Receiver-based Approach

In this method, Kafka's data is received through receivers and stored in Spark's memory before processing. It uses the simple Kafka consumer API, and Spark's receiver must be reliable or unreliable. If the receiver fails, data can be lost unless you configure Spark with Write Ahead Logs (WAL).

Key points:

  • Data is serialized into Spark’s memory before processing.
  • Potential for data loss unless WAL is configured in Spark.
  • This approach uses extra resources because the receivers run in Spark executors.

2. Direct Approach

This modern method introduced in Spark 1.3 allows Kafka to be integrated with Spark without the need for receivers. Each RDD generated in this approach contains data from a specific Kafka topic partition for a defined range of offsets.

Key points:

  • More efficient as it reduces the number of reads and writes.
  • No risk of data loss even if Spark processing is delayed.
  • Simplifies parallelism without needing multiple receivers.

Technical Explanation

Using direct stream in Spark, a DStream is created directly from Kafka, which reads data from the partitions. Offsets are managed by Spark itself, and not by Kafka. You can setup Spark to either read the latest offset or from the smallest (beginning of the stream):

scala
1import org.apache.kafka.common.serialization.StringDeserializer
2import org.apache.spark.streaming.kafka010.ConsumerStrategies.Subscribe
3import org.apache.spark.streaming.kafka010.LocationStrategies.PreferConsistent
4import org.apache.spark.streaming.kafka010._
5
6val kafkaParams = Map[String, Object](
7  "bootstrap.servers" -> "localhost:9092",
8  "key.deserializer" -> classOf[StringDeserializer],
9  "value.deserializer" -> classOf[StringDeserializer],
10  "group.id" -> "use_a_separate_group_id_for_each_stream",
11  "auto.offset.reset" -> "latest",
12  "enable.auto.commit" -> (false: java.lang.Boolean)
13)
14
15val topics = Array("topicA", "topicB")
16val stream = KafkaUtils.createDirectStream[String, String](
17  streamingContext,
18  PreferConsistent,
19  Subscribe[String, String](topics, kafkaParams)
20)

In this code, PreferConsistent distributes the partitions uniformly across the available executors. The consumer uses Subscribe strategy to subscribe to a fixed collection of topics.

Processing and Storing Offsets

One of the challenges in Kafka-Spark integration is managing offsets. Spark Streaming provides a mechanism to track consumed offsets and handle them manually. After processing, you can commit offsets to ensure accurate processing state across consumer restarts or failures.

Key Considerations

Here’s a table summarizing some key points when using Kafka Consumer in Spark Streaming:

FeatureReceiver-based ApproachDirect Approach
Risk of data lossHigh (unless WAL)Low
EfficiencyModerateHigh
Management of Kafka offsetsManualManaged by Spark
Setup complexityModerateLow
Resource usageHighModerate

Conclusion

The Direct Approach is generally more efficient and reliable for integrating Kafka with Spark Streaming. It allows for more straightforward parallel processing and offset management. When real-time processing needs are critical, and data loss must be avoided, leveraging the direct approach with manual offset control becomes essential. This not only offers consistency and fault tolerance but also optimizes resource usage across the distributed environment.


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.