Ответ
Основа Apache Kafka — это распределённый, отказоустойчивый и неизменяемый журнал фиксации (commit log), который работает по принципу append-only (только дозапись в конец).
Как это устроено:
Топик (Topic):
- Логическая категория или именованный поток, в который продюсеры публикуют сообщения. Например,
user-registrations
илиorder-updates
.
- Логическая категория или именованный поток, в который продюсеры публикуют сообщения. Например,
Партиция (Partition):
- Каждый топик разделяется на одну или несколько партиций. Партиция — это и есть физический, упорядоченный и неизменяемый лог-файл.
- Запись в партицию всегда происходит в конец (append-only).
- Порядок сообщений гарантируется только в пределах одной партиции.
Офсет (Offset):
- Каждое сообщение внутри партиции имеет уникальный последовательный идентификатор — офсет (например, 0, 1, 2, ...).
- Офсет позволяет консьюмерам отслеживать свою позицию чтения и перечитывать сообщения при необходимости.
Репликация (Replication):
- Для отказоустойчивости каждая партиция реплицируется на несколько брокеров (серверов Kafka). Одна реплика является лидером (принимает запись), остальные — последователями (копируют данные).
Пример записи в Kafka на Go (с использованием segmentio/kafka-go
):
package main
import (
"context"
"log"
"github.com/segmentio/kafka-go"
)
func main() {
w := &kafka.Writer{
Addr: kafka.TCP("localhost:9092"),
Topic: "my-topic",
Balancer: &kafka.LeastBytes{},
}
err := w.WriteMessages(context.Background(),
kafka.Message{
Key: []byte("Key-A"),
Value: []byte("Hello Kafka!"),
},
)
if err != nil {
log.Fatal("failed to write messages:", err)
}
if err := w.Close(); err != nil {
log.Fatal("failed to close writer:", err)
}
}
Преимущества такого подхода:
- Высокая производительность: Последовательная запись на диск — одна из самых быстрых дисковых операций.
- Горизонтальная масштабируемость: Нагрузка распределяется по партициям и брокерам.
- Отказоустойчивость: Репликация данных защищает от потери сообщений при сбое брокера.
- Гибкость для потребителей: Консьюмеры могут читать данные со своей скоростью, перечитывать их и работать независимо друг от друга.