Архитектура Apache Kafka: основные компоненты, как продюсеры и консюмеры связаны между собой? Что такое ребалансировка? Как обеспечить последовательное чтение сообщений?
Answer from AI
sobes.tech AI
Apache Kafka — это распределённая платформа потоковой передачи данных, построенная на основе следующих основных компонентов:
- Producer (Продюсер) — приложение, которое публикует (отправляет) сообщения в топики Kafka.
- Consumer (Консюмер) — приложение, которое читает сообщения из топиков.
- Topic (Топик) — логическая категория или канал, куда продюсеры отправляют сообщения.
- Partition (Раздел) — топик разбивается на несколько партиций для масштабируемости и параллельной обработки.
- Broker (Брокер) — сервер Kafka, который хранит данные и обслуживает запросы продюсеров и консюмеров.
- Consumer Group (Группа консюмеров) — набор консюмеров, которые совместно читают данные из топика, распределяя партиции между собой.
Связь продюсеров и консюмеров происходит через топики и партиции. Продюсер отправляет сообщения в определённый топик, а консюмеры, входящие в группу, получают сообщения из партиций этого топика. Каждая партиция доставляется только одному консюмеру в группе, что обеспечивает параллельную обработку без дублирования.
Ребалансировка (Rebalance) — процесс перераспределения партиций между консюмерами внутри группы. Это происходит, когда консюмеры присоединяются к группе, покидают её или когда меняется количество партиций. Ребалансировка гарантирует, что каждая партиция назначена ровно одному консюмеру.
Для обеспечения последовательного чтения сообщений необходимо:
- Гарантировать, что сообщения из одной партиции читаются одним консюмером последовательно.
- Использовать ключи сообщений при отправке, чтобы все сообщения с одним ключом попадали в одну партицию (partitioning by key).
- Обрабатывать сообщения в консюмере синхронно или с контролем порядка.
Пример на Go с использованием библиотеки sarama (упрощённо):
consumer, err := sarama.NewConsumerGroup(brokers, groupID, config)
// В обработчике ConsumerGroupHandler реализуется метод ConsumeClaim, где читаются сообщения из партиций последовательно
func (h *consumerGroupHandler) ConsumeClaim(sess sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {
for msg := range claim.Messages() {
fmt.Printf("Message topic:%s partition:%d offset:%d key:%s value:%s\n", msg.Topic, msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))
sess.MarkMessage(msg, "")
}
return nil
}
Таким образом, последовательность гарантируется в пределах партиции, а ключи помогают направлять связанные сообщения в одну партицию.