Как правильно выбрать количество партиций и консьюмеров в Kafka?

«Как правильно выбрать количество партиций и консьюмеров в Kafka?» — вопрос из категории Брокеры сообщений, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Количество партиций и консьюмеров в Kafka должно быть сбалансировано для оптимальной производительности и масштабируемости.

Ключевые принципы:

  • Максимум параллелизма: В рамках одной consumer group количество одновременно работающих консьюмеров не может превышать количество партиций в топике.
  • Запас для масштабирования: Количество партиций должно быть больше текущего числа консьюмеров, чтобы обеспечить возможность горизонтального масштабирования.

Плохие практики (из вопроса):

  • 1 партиция, 1 консьюмер: Нет параллелизма, обработка ограничена скоростью одного потока.
  • 3 партиции, 10 консьюмеров: 7 консьюмеров будут простаивать, так как максимум 3 могут быть активными.

Рекомендуемый подход:

  1. Оцените пиковую нагрузку и желаемую пропускную способность.
  2. Установите количество партиций равным планируемому максимальному числу консьюмеров плюс запас (обычно 20-30%).
    • Пример: Если ожидается до 8 консьюмеров, создайте 10 партиций.
  3. Увеличить количество партиций можно, но уменьшить — только путем создания нового топика и копирования данных.

Пример настройки с помощью AdminClient API:

import org.apache.kafka.clients.admin.*;
import java.util.Collections;
import java.util.Properties;

// Создание топика с 10 партициями и фактором репликации 3
try (AdminClient adminClient = AdminClient.create(adminProps)) {
    NewTopic newTopic = new NewTopic("orders", 10, (short) 3);
    CreateTopicsResult result = adminClient.createTopics(Collections.singleton(newTopic));
    result.all().get(); // Синхронное ожидание создания
}

// Конфигурация consumer group
Properties consumerProps = new Properties();
consumerProps.put("bootstrap.servers", "localhost:9092");
consumerProps.put("group.id", "order-processors");
consumerProps.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
consumerProps.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
// Запуск 10 консьюмеров в группе "order-processors" позволит обрабатывать все 10 партиций параллельно.