11 вопросов
Kafka - распределенная потоковая платформа: хранит сообщения в топиках разбитых на партиции, обеспечивает персистентность, масштабирование и повторное чтение. Производители пишут в топики, потребители читают из партиций (consumer groups). Используют для логов, событий, стриминга, очередей. В Go популярны библиотеки: confluent-kafka-go, segmentio/kafka-go, sarama.
conn, _ := kafka.DialLeader(ctx, "tcp", "localhost:9092", "topic", 0)
conn.WriteMessages(kafka.Message{Value: []byte("hello")})Топик разбит на партиции; сообщения с одним ключом попадают в одну партицию (партиционирование по ключу). Параллелизм потребления ограничен числом партиций. В Go при создании топика или при продюсинге указывают число партиций; consumer подключается к партициям (в группе партиции распределяются между участниками). Увеличение партиций после создания возможно, но меняет распределение ключей.
msg := kafka.Message{Key: []byte(userID), Value: data}
w.WriteMessages(ctx, msg)Consumer group - набор потребителей с общим group.id. Каждая партиция топика назначается одному потребителю в группе; при добавлении/уходе потребителей происходит rebalance - перераспределение партиций. В Go подключаются к Kafka с group ID; библиотека участвует в rebalance. Обработка сообщений идемпотентна или с учетом дублей при повторной доставке.
r := kafka.NewReader(kafka.ReaderConfig{
Brokers: []string{"localhost:9092"},
Topic: "events",
GroupID: "processor",
})Offset - позиция потребителя в партиции. После обработки сообщения consumer коммитит offset (в Kafka или в группе). При перезапуске чтение продолжается с закоммиченного offset. В Go: автоматический коммит по таймауту или ручной после успешной обработки (CommitMessages). At-least-once: коммит после обработки; при сбое после обработки но до коммита - повторная доставка. Идемпотентность обработки важна.
for {
msg, _ := r.FetchMessage(ctx)
process(msg)
r.CommitMessages(ctx, msg)
}acks=0 - не ждать подтверждения. acks=1 - лидер партиции подтвердил. acks=all - лидер и реплики подтвердили. Идемпотентный продюсер (enable.idempotence=true) избегает дублей при ретраях. В Go настраивают при создании продюсера; для критичных сообщений acks=all и идемпотентность. Транзакции (транзакционный продюсер + read_committed на consumer) дают exactly-once семантику в рамках Kafka.
w := &kafka.Writer{
RequiredAcks: kafka.RequireAll,
Async: false,
}At-most-once: коммит до обработки; при падении после коммита сообщение теряется. At-least-once: коммит после обработки; при падении после обработки но до коммита - повторная доставка (идемпотентность обработки). Exactly-once: транзакции продюсера + read_committed и идемпотентный consumer, или семантика в приложении (дедупликация по ключу). В Go чаще реализуют at-least-once с идемпотентной обработкой.
Kafka: большие объемы, ретроспектива (хранение, повторное чтение), потоковая обработка, несколько потребителей одного потока, партиционирование по ключу. RabbitMQ: классические очереди, гибкая маршрутизация (exchanges), приоритеты, TTL, меньше латентность для простых сценариев. В Go для событийной шины и логов чаще Kafka; для задач воркерам и простых очередей - RabbitMQ или облачные очереди (SQS).
Exactly-once в Kafka: транзакционный продюсер (отправка в транзакции), consumer с read_committed (читает только закоммиченные транзакции), идемпотентность на стороне приложения (дедупликация по ключу сообщения или по бизнес-ключу). В Go поддержка зависит от библиотеки; confluent-kafka и kafka-go поддерживают транзакции. Альтернатива - at-least-once + дедупликация в БД (уникальный ключ + INSERT ... ON CONFLICT).
Kafka реплицирует каждую партицию на несколько брокеров (replication.factor). Один брокер - лидер, остальные - реплики (ISR, In-Sync Replicas). При падении лидера контроллер автоматически выбирает нового из ISR. Продюсер с acks=all получает подтверждение только после записи во все ISR-реплики. Параметр min.insync.replicas задает минимум синхронных реплик для записи. Типичная конфигурация (RF=3, min.insync=2, acks=all) выдерживает потерю одного брокера без остановки и потери данных. Consumer при перезапуске продолжает с закоммиченного offset, не теряя позицию.
Kafka Connect - фреймворк для потоковой передачи данных между Kafka и внешними системами (БД, S3, Elasticsearch). Connectors - источник (source) или приемник (sink). В Go приложении обычно не используют Connect напрямую; пишут продюсеры и консьюмеры на Go. Connect полезен для готовых пайплайнов (например, Debezium для CDC в Kafka).
Schema Registry хранит схемы сообщений (Avro, JSON Schema, Protobuf); версионирование и совместимость. Продюсер и консьюмер получают/проверяют схему по id в заголовке сообщения. В Go используют клиент Schema Registry (confluentinc/confluent-kafka-go с schema_registry) для сериализации/десериализации. Удобно при эволюции формата и нескольких сервисах на разных языках.
sr, _ := schemaregistry.NewClient(schemaregistry.NewConfig("http://localhost:8081"))
encoder, _ := avro.NewGenericAvroSerializer(sr, ...)
payload, _ := encoder.Serialize("topic", msg)