Kafka
High Level Consumer
Delayed Queue Implementation
Message Queuing
Distributed Systems

Kafka - Delayed Queue implementation using high level consumer

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 Kafka is a potent distributed event streaming platform capable of handling trillions of events a day. Initially conceived as a messaging queue, Kafka is based on an abstraction of a distributed commit log. Since its inception, it has developed into a full-fledged event streaming platform.

Understanding Delayed Queue

In many real-world applications, there is a need to delay the processing of messages or tasks. These scenarios can include scheduling tasks to run after a certain period, delaying retries after a failed operation, or simply spacing out the processing of events.

Kafka itself does not support delayed queues natively in the way that some other message brokers like RabbitMQ do. However, you can implement such a feature using Kafka's primitives, specifically through the use of high-level consumers and topic design.

Implementation of Delayed Queues in Apache Kafka

Implementing a delayed queue using Kafka involves a few systematic steps. Here’s how you can achieve it with high-level consumers:

Step 1: Topic Design

You’ll need to create one or multiple topics where the messages will be initially sent. This topic can act as a "waiting room" for messages before they are ready to be processed.

Step 2: Message Stamping

When a producer sends a message to the topic, it can add a timestamp indicating when the message should be available for consumption. This is typically done by inserting a delay value into the message itself, often in the headers.

Step 3: Scheduler Consumer

You create a high-level consumer whose job is to poll messages from the initial topic continuously. This consumer will check the timestamp of each message. If the current time is less than the target time of the message (current time < target time + delay), the message is not ready to be processed. Instead, the consumer sends this message to a secondary topic, often called a "delay topic."

java
1Properties props = new Properties();
2props.put("bootstrap.servers", "localhost:9092");
3props.put("group.id", "test");
4props.put("enable.auto.commit", "true");
5props.put("auto.commit.interval.ms", "1000");
6props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
7props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
8
9try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props)) {
10    consumer.subscribe(Arrays.asList("initial_topic"));
11    while (true) {
12        ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
13        for (ConsumerRecord<String, String> record : records) {
14            long messageTime = getMessageTime(record);
15            long delay = getDelay(record);
16            if (System.currentTimeMillis() < messageTime + delay) {
17                // Resend to delay topic
18            } else {
19                // Process the message
20            }
21        }
22    }
23}

Step 4: Delay Topic and Reprocessing

Messages in the delay topic are then consumed by another consumer, which checks if the delay has elapsed. If not, the message is sent back to the delay topic. If the delay has elapsed, it goes to a "ready" topic or is processed immediately.

Step 5: Final Consumer

A final consumer reads from the "ready" topic where all the conditions are met for message processing.

Key Challenges and Considerations:

  1. Multiple Consumers: Managing multiple consumers and ensuring they are in sync can be challenging.
  2. Resource Utilization: Continuously polling and re-writing messages can be resource-intensive.
  3. At-Least-Once Delivery: Ensuring that messages are not lost but are also not overly duplicated.

Summary Table of Steps and Components

StepComponentDescription
1Initial TopicThe topic where messages are first sent.
2Message StampingAdding delay information in the message itself, typically in the headers.
3Scheduler ConsumerHigh-level consumer that re-routes messages to the delay topic when not ready.
4Delay TopicTemporary storage for messages not yet ready to be processed.
5Final ConsumerConsumes messages that are ready for processing.

Additional Enhancements

  • Efficient Polling: Implement smart polling mechanics to reduce CPU cycles, such as increasing the poll interval dynamically.
  • Retry Logic: Incorporate logic to handle messages that fail to process even after the delay period.
  • Scalability: Enhance the system to handle more topics and partitions as the load increases.

Implementing a delayed queue in Kafka, while not straightforward, can be highly effective and scalable using the right architectural approaches and Kafka’s robust streaming capabilities.


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.