In this lesson, you will learn how to fine-tune producer settings to strike the ideal balance between high-volume data throughput and real-time delivery latency.
When producers send messages to Kafka, they don't necessarily send them one by one. Sending every message immediately results in high overhead, while waiting too long to group them increases latency. To optimize this, we manipulate two primary configurations: batch.size and linger.ms.
Balancing Throughput and Latency
batch.size: This sets the maximum number of bytes the producer will attempt to batch together for a single partition. Increasing this value allows for better compression and fewer I/O requests, boosting throughput. However, if your traffic is low, a large batch size might sit partially empty, waiting for more data.linger.ms: This introduces a small artificial delay (in milliseconds) before sending a batch. By settinglinger.ms > 0, you instruct the producer to wait until the batch is full or the timer expires. This is the "sweet spot" for throughput; it encourages the grouping of messages that arrive in rapid succession.
If your application requires extremely low latency, you might set linger.ms to 0. If your goal is high throughput during heavy traffic, setting linger.ms to 5 or 10 allows batches to fill up efficiently without significantly hurting the end-user experience.
Here is how you might configure these in a producer:
Properties props = new Properties();
// Batch up to 64KB of data before sending
props.put("batch.size", 65536);
// Wait up to 10ms to allow more messages to join the batch
props.put("linger.ms", 10);
The trade-off is clear: higher linger.ms and batch.size increase your total system throughput at the cost of slight delays for the first message in a batch. Conversely, smaller values minimize latency but increase the CPU and network overhead on your brokers, potentially becoming a bottleneck. Monitor your record-send-rate and request-latency-avg metrics to find the values that match your specific SLAs.
Key Takeaway: Use batch.size to group data into efficient chunks and linger.ms to add a controlled delay, effectively trading off minor latency to significantly increase overall cluster throughput.