> Как работает масштабирование Kafka: репликация и шардирование (Go)
Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы
Компании: Ozon
Стек: Go
> Пример ответа
Короткий ответ
Kafka масштабируется горизонтально через шардирование топиков на партиции и репликацию партиций между брокерами. Партиции - единица параллелизма и упорядоченности: внутри партиции порядок гарантирован, между партициями - нет. Репликация обеспечивает отказоустойчивость: каждая партиция имеет leader и follower-реплики на разных брокерах. Продюсеры пишут в leader, консьюмеры читают из leader. При сбое брокера контроллер Kafka выбирает новую leader-реплику из in-sync replicas (ISR).
Подробное объяснение
Шардирование (партиционирование)
Топик разбивается на N партиций. Каждая партиция - это упорядоченный лог с offset. Распределение партиций по брокерам кластера - это и есть шардирование. Ключевые следствия:
- Пропускная способность топика масштабируется добавлением партиций (при условии, что консьюмер-группа имеет достаточно консьюмеров).
- Порядок сообщений гарантируется только в пределах одной партиции.
- Выбор партиции определяется ключом сообщения (hash) или round-robin, если ключ null.
- Количество партиций задаётся при создании топика и может быть увеличено, но уменьшение не поддерживается (это trade-off: увеличение ломает ключевой порядок).
Репликация
Каждая партиция имеет replication.factor реплик (обычно 3). Одна реплика - leader, остальные - followers. Механика:
- Продюсеры и консьюмеры работают только с leader.
- Followers реплицируют данные от leader через fetch-запросы.
- Реплика считается in-sync (ISR), если она не отстала от leader больше, чем на
replica.lag.time.max.ms(по умолчанию 30 секунд). - При сбое leader контроллер выбирает новую leader из ISR. Если ISR пуст, возможен выбор из out-of-sync реплик при
unclean.leader.election.enable=true- это trade-off между доступностью и консистентностью.
Взаимодействие шардирования и репликации
Каждая партиция - это отдельная единица репликации. Например, топик с 10 партициями и replication.factor=3 создаёт 30 реплик, распределённых по брокерам. Kafka-администратор может управлять распределением через kafka-reassign-partitions.sh.
Роль контроллера
Один из брокеров - контроллер. Он отвечает за:
- выбор leader-реплик при сбоях
- обработку изменений в составе кластера
- управление репликацией при добавлении/удалении брокеров
На практике
В Go-проектах с Kafka (через segmentio/kafka-go или confluent-kafka-go) важно учитывать:
- Партиционирование на стороне продюсера: если нужен строгий порядок по ключу (например, по user_id), ключ должен быть стабильным. При увеличении числа партиций порядок по ключу ломается.
- Консьюмер-группы: количество консьюмеров в группе не должно превышать число партиций - лишние будут простаивать.
- Идемпотентный продюсер и
acks=allдля гарантий доставки - но это снижает throughput. - Мониторинг: следить за
UnderReplicatedPartitionsиIsrShrinksPerSec- это индикаторы проблем с репликацией.
Пример кода
GO// Продюсер с ключом для шардированияpackage mainimport ("context""fmt""time""github.com/segmentio/kafka-go")func main() {writer := kafka.Writer{Addr: kafka.TCP("localhost:9092"),Topic: "orders",Balancer: &kafka.Hash{}, // шардирование по ключуRequiredAcks: kafka.RequireAll, // acks=allAsync: false,}defer writer.Close()ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)defer cancel()// Ключ определяет партицию - гарантия порядка для user_iderr := writer.WriteMessages(ctx, kafka.Message{Key: []byte("user_123"),Value: []byte(`{"order_id": 42}`),})if err != nil {fmt.Printf("write failed: %v\n", err)return}fmt.Println("message written to partition by hash of key")}
GO// Консьюмер с обработкой партицийpackage mainimport ("context""fmt""log""github.com/segmentio/kafka-go")func main() {reader := kafka.NewReader(kafka.ReaderConfig{Brokers: []string{"localhost:9092"},Topic: "orders",GroupID: "order-processor",Partition: 0, // можно читать конкретную партициюMinBytes: 10e3,MaxBytes: 10e6,})defer reader.Close()ctx := context.Background()for {msg, err := reader.ReadMessage(ctx)if err != nil {log.Printf("read error: %v", err)continue}fmt.Printf("partition=%d offset=%d key=%s value=%s\n",msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))}}
Как отвечать на собеседовании
Начните с определения двух осей масштабирования: партиционирование - для параллелизма, репликация - для надёжности. Объясните, что партиция - атомарная единица и упорядоченности, и репликации. Упомяните ISR и роль контроллера. Если спросят про trade-off - говорите про unclean.leader.election и увеличение числа партиций. Для senior-уровня добавьте детали про выбор leader, min.insync.replicas и влияние на гарантии доставки. Не углубляйтесь в реализацию лога на диске, если не спрашивают.
Что проверяет интервьюер
- Понимание, что партиции - это шардирование, а реплики - отказоустойчивость.
- Знание механики ISR и последствий для консистентности.
- Умение объяснить, почему порядок гарантирован только внутри партиции.
- Понимание влияния числа партиций на throughput и на операции с ключами.
- Знание, как Kafka восстанавливается после сбоя брокера.
Типичные ошибки
- Путать партиции и реплики: говорить, что реплики - это копии топика целиком.
- Утверждать, что Kafka гарантирует глобальный порядок сообщений.
- Не упоминать ISR при разговоре о выборе leader.
- Считать, что увеличение партиций всегда улучшает производительность - на самом деле это увеличивает число файлов и накладные расходы на репликацию.
- Забывать, что консьюмеров в группе не должно быть больше партиций.
- Не учитывать, что изменение числа партиций ломает порядок по ключу.
> Похожие задачи по Go
Какие плюсы и минусы шардирования по сообщениям и по пользователям
Какие есть варианты решения проблемы медленной работы сервиса аналитики при создании заказа
Зачем создавать отдельный сервис воркер для аналитики вместо обработки в ордер сервисе
Где размещать воркеры, читающие данные из Kafka и отправляющие в аналитику
> Похожие задачи по backend
Какие плюсы и минусы шардирования по сообщениям и по пользователям
Какие есть варианты решения проблемы медленной работы сервиса аналитики при создании заказа
Зачем создавать отдельный сервис воркер для аналитики вместо обработки в ордер сервисе
Где размещать воркеры, читающие данные из Kafka и отправляющие в аналитику
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью