> Как масштабировать Kafka при высокой нагрузке (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Wildberries

Стек: Go

> Пример ответа

Короткий ответ

Масштабирование Kafka при высокой нагрузке - это комбинация вертикального и горизонтального масштабирования: увеличение числа партиций для параллелизма, добавление брокеров для распределения нагрузки, настройка producer batch size и linger.ms, оптимизация consumer group с правильным числом consumer'ов. Ключевой trade-off - порядок сообщений внутри партиции против пропускной способности. Для Go важно использовать segmentio/kafka-v2 или franz-go, которые эффективно работают с batching и compression.

Подробное объяснение

Kafka масштабируется горизонтально, но есть жёсткие ограничения. Основные точки роста:

  1. Партиции - единица параллелизма. Одна партиция обслуживается одним consumer в группе. Увеличение партиций даёт больше параллелизма, но каждая партиция имеет overhead: файловые дескрипторы, память на индексы, репликация. Практический предел - 10-20 тысяч партиций на кластер.

  2. Брокеры - распределяют партиции и реплики. Добавление брокеров не требует перебалансировки данных, но требует увеличения replication factor для отказоустойчивости. Важно: throughput кластера ограничен не CPU, а дисковым I/O и сетью.

  3. Producer - главный bottleneck при высокой нагрузке. Ключевые параметры:

    • batch.size - больше batch = меньше round-trips, но больше latency
    • linger.ms - задержка перед отправкой batch
    • compression.type - snappy/lz4/zstd снижают сетевой трафик
    • acks - 0/1/all, trade-off между надёжностью и throughput
  4. Consumer - число consumer'ов в группе должно быть ≤ числу партиций. Если consumer'ов больше - часть простаивает. Для Go важно использовать Fetch с большим MaxWait и MinBytes, чтобы получать большие batch'и.

  5. Репликация - replication factor 3 - стандарт, но каждый follower потребляет сетевой трафик. При высокой нагрузке следите за ISR (in-sync replicas) - если follower'ы не успевают, producer получит NotEnoughReplicas.

  6. Сеть - Kafka чувствителен к latency между брокерами. Размещайте брокеров в одной зоне доступности, если нет жёстких требований к геораспределению.

  7. Диски - используйте NVMe SSD. Kafka пишет последовательно, но fsync на каждый batch убивает throughput. Настройте log.flush.interval.messages и log.flush.interval.ms - trade-off между durability и скоростью.

  8. Go-специфика - стандартный sarama (Shopify) имеет проблемы с производительностью на больших batch'ах. Используйте segmentio/kafka-go или franz-go - они поддерживают AsyncProducer с каналами и эффективный batching.

На практике

Типичный сценарий: 100k msg/s, размер сообщения 1KB. Что делаем:

  1. Партиции: 24-48 (кратно числу consumer'ов). Не делайте 1000 партиций - это overhead.
  2. Producer: batch.size=65536 (64KB), linger.ms=10, compression=snappy, acks=1.
  3. Consumer: Fetch.MinBytes=1MB, Fetch.MaxWait=500ms, MaxPartitionBytes=10MB.
  4. Брокеры: 3-5 брокеров, replication factor 3, num.network.threads=8, num.io.threads=16.
  5. Мониторинг: следите за UnderReplicatedPartitions, RequestHandlerAvgIdlePercent, BytesInPerSec.

Важный момент: если нагрузка скачкообразная (например, Black Friday), не масштабируйте партиции постоянно - это дорого. Лучше держать запас по партициям и увеличивать число consumer'ов в группе динамически.

Пример кода

GO
// Producer с оптимизацией batch'ей (segmentio/kafka-go)
package main
import (
"context"
"time"
"github.com/segmentio/kafka-go"
)
func newProducer(brokers []string, topic string) *kafka.Writer {
return &kafka.Writer{
Addr: kafka.TCP(brokers...),
Topic: topic,
Balancer: &kafka.Hash{}, // или RoundRobin для равномерности
BatchSize: 65536, // 64KB
BatchTimeout: 10 * time.Millisecond,
Compression: kafka.Snappy,
RequiredAcks: kafka.RequireOne, // acks=1
Async: true, // не блокируемся на каждом сообщении
}
}
// Consumer с большими batch'ами
func newConsumer(brokers []string, topic string, groupID string) *kafka.Reader {
return kafka.NewReader(kafka.ReaderConfig{
Brokers: brokers,
Topic: topic,
GroupID: groupID,
MinBytes: 1e6, // 1MB
MaxBytes: 10e6, // 10MB
MaxWait: 500 * time.Millisecond,
CommitInterval: time.Second,
})
}
// Пример использования producer
func sendBatch(ctx context.Context, w *kafka.Writer, messages [][]byte) error {
for _, msg := range messages {
err := w.WriteMessages(ctx, kafka.Message{Value: msg})
if err != nil {
return err
}
}
return nil
}

Как отвечать на собеседовании

Начните с главного: масштабирование Kafka - это не только добавление брокеров, а комплексное изменение конфигурации на всех уровнях. Скажите про партиции как единицу параллелизма, затем про producer batching, затем про consumer group. Упомяните trade-off между latency и throughput. Если спросят про Go - обязательно упомяните, что sarama устарел для high-load, используйте segmentio или franz-go. Приведите конкретные цифры: 24-48 партиций, batch 64KB, linger 10ms. Покажите, что понимаете ограничения: порядок сообщений, ребалансировка, ISR.

Что проверяет интервьюер

  • Понимание модели параллелизма Kafka: партиции → consumer'ы
  • Знание параметров producer/consumer и их влияния на throughput
  • Умение находить bottleneck'и: сеть, диск, CPU
  • Понимание trade-off'ов: надёжность vs скорость, порядок vs параллелизм
  • Практический опыт с Go-клиентами и их особенностями
  • Способность предложить конкретные цифры и конфигурации, а не абстрактные "увеличить партиции"

Типичные ошибки

  • Говорить "добавьте брокеров" без учёта, что партиции не перераспределяются автоматически
  • Предлагать бесконечно увеличивать партиции - забывают про overhead
  • Не упоминать про compression - это первое, что даёт 2-3x выигрыш
  • Путать acks=0 с надёжностью - это потеря данных при любой ошибке
  • Использовать sarama в Go без оговорки, что он медленный на больших batch'ах
  • Не учитывать, что consumer'ов не может быть больше партиций - это классическая ошибка
  • Забывать про replication.factor - при высокой нагрузке follower'ы отстают, и producer получает ошибки
  • Предлагать linger.ms=0 для "ускорения" - это убивает batching и увеличивает нагрузку на сеть

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью