Как использовать Kafka для распределения большого количества задач между воркерами?
Что проверяют
Понимаете ли вы, что Kafka это журнал с партициями, а не очередь задач, и как из этого следует модель параллелизма. Почти всегда уточняют: что будет, если задача обрабатывается дольше пяти минут, и как не выполнить её дважды.
Как отвечать
- топик и партиции: задачи пишутся в топик, единица параллелизма это партиция. Если у задачи есть ключ, все сообщения с ним попадают в одну партицию и обрабатываются по порядку;
- consumer group: воркеры с одним
group.idделят партиции между собой, каждую партицию в группе читает ровно один воркер. Воркеров больше, чем партиций, значит лишние простаивают, поэтому партиций заводят с запасом. Число партиций можно увеличить, но не уменьшить, и при увеличении меняется привязка ключей; - коммит оффсетов: и в
confluent-kafka, и вkafka-pythonпо умолчанию включёнenable.auto.commit, и оффсет может закоммититься раньше, чем задача выполнена. Для задач правильнее выключить автокоммит и вызыватьconsumer.commit()после обработки. Это даёт at-least-once, значит обработчик должен быть идемпотентным; - долгие задачи: если между вызовами
poll()проходит большеmax.poll.interval.ms(по умолчанию 5 минут), воркер считается мёртвым, группа ребалансируется, и задачу берёт другой. Помогают меньшие пачки за один опрос и вынос тяжёлой работы в отдельный пул сpause()иresume()партиций, чтобы цикл опроса продолжал крутиться; - ошибки: оффсет это позиция в партиции, подтвердить отдельное сообщение нельзя. Упавшие задачи уводят в retry-топик и дальше в DLQ, а не держат партицию.
Из Python обычно берут confluent-kafka (обёртка над librdkafka) или aiokafka для asyncio. Если нужны приоритеты, отложенный запуск и подтверждение каждой задачи, честнее предложить Celery поверх RabbitMQ или Redis.
Где спотыкаются
Добавляют воркеров сверх числа партиций и ждут роста скорости. Скорость не растёт, новые потребители просто стоят.
Оставляют автокоммит. Воркер падает посреди задачи, оффсет уже сдвинут, задача потеряна без следа.
Не думают про медленное сообщение. Одна зависшая задача держит всю партицию, и задачи за ней ждут, даже если остальные воркеры свободны.