Типичные ошибки и антипаттерны

Урок-чеклист: собираем главные грабли Kafka в одном месте, чтобы не наступать на них в проде.

Большинство проблем с Kafka — не баги платформы, а предсказуемые ошибки конфигурации и дизайна: неверное число партиций, плохой ключ, тяжёлые сообщения, неаккуратные гарантии.

Зачем это нужно

Kafka прощает многое, пока нагрузка мала. Грабли всплывают на масштабе — и сразу больно. Зная их заранее, вы закладываете правильные решения с самого начала, а не переделываете прод под пожаром.

Карта типичных ошибок

ОшибкаСимптомЛечение
Мало партицийнизкий потолок параллелизма, консьюмеры простаиваютоценить нагрузку, заложить партиции с запасом
Тяжёлые сообщенияраздутая память, лаг, давление на сетьблоб в хранилище, в Kafka — ссылку
Неверный ключhot partition или потеря порядкаключ высокой кардинальности, но удерживающий порядок сущности
Долгая обработка в pollребаланс-штормы, растущий лагменьше max.poll.records, вынести работу из poll
acks=1 / RF=1потеря данных при сбоеacks=all, RF=3, min.insync.replicas=2
Сырой JSON без схемыломающие изменения формата в продеSchema Registry, совместимая эволюция

Мало партиций

Создали топик с 1-2 партициями «на старте» — и упёрлись в потолок: сколько консьюмеров ни добавляй, читают только 1-2. Увеличить число партиций потом можно, но это ломает порядок по ключу. Оценивайте пиковую нагрузку заранее и закладывайте запас.

Тяжёлые сообщения и неверный ключ

Сообщения по мегабайту раздувают батчи, память продюсера/брокера и лаг. Крупные данные (картинки, документы) кладите в S3/MinIO, а в Kafka передавайте ссылку и метаданные. Неверный ключ — вторая классика: ключ status или country с парой значений создаёт hot partition; отсутствие ключа теряет порядок связанных событий.

Ребаланс-штормы и слабые гарантии

  Антипаттерн "тяжёлый poll":
    poll() -> 5000 записей -> обработка 2 минуты -> исключение из группы
    -> ребаланс -> снова poll -> снова исключение -> ШТОРМ

  Лечение: max.poll.records поменьше, обработка быстрее/асинхронно,
           heartbeat в отдельном потоке (современные клиенты так и делают)

Как работает под капотом

Почти все эти грабли — следствие того, что мы уже разобрали по частям. Партиции — единица параллелизма, поэтому их нехватка жёстко ограничивает масштаб. Ключ определяет партицию и порядок, поэтому его выбор балансирует равномерность и упорядоченность. Гарантии (acks/RF/ISR) — это явный компромисс скорость-против-надёжности, и «по умолчанию быстро» часто значит «по умолчанию небезопасно». Понимание механики из предыдущих разделов превращает этот список из набора суеверий в осознанные инженерные решения.

Частые ошибки

  • Тюнить по советам из интернета без понимания. Параметры взаимосвязаны; меняйте осознанно, измеряя эффект.
  • Один топик «на всё». Разные типы событий с разными требованиями к retention/партициям лучше разнести.
  • Игнорировать обратное давление. Если потребитель не успевает, лаг растёт — нужно масштабировать чтение, а не «надеяться».

Итоги

  • Главные грабли: мало партиций, тяжёлые сообщения, плохой ключ, тяжёлый poll, слабые гарантии.
  • Лечатся осознанным дизайном: запас партиций, ссылки вместо блобов, правильный ключ, acks=all/RF=3.
  • Список перестаёт быть суеверием, когда понимаешь механику партиций, ключей и гарантий.
Проверьте себя
1. Как правильно поступить с очень большими сообщениями?
AСлать как есть в Kafka
BХранить блоб в объектном хранилище, а в Kafka передавать ссылку и метаданные
CУвеличить число брокеров
DОтключить репликацию
2. Чем грозит ключ с низкой кардинальностью (например, status)?
AУскорением чтения
BHot partition: большая часть трафика валится в одну партицию, параллелизм теряется
CПотерей реплик
DРостом числа топиков
3. Как избежать ребаланс-штормов из-за тяжёлого poll?
AУвеличить max.poll.records
BУменьшить max.poll.records и ускорить/вынести обработку из poll-цикла
CОтключить heartbeat
DСоздать один топик на всё