Распределенное хранилище - это система, которая, как правило, работает на нескольких машинах, каждая из этих машин в свою очередь является кусочком хранилища.
Для пользователя это все представляется в виде единого целого.
Вертикальное масштабирование - это когда мы добавляем нашей машине ресурсы (проц, память, винт и т.п.).
Такое масштабирование имеет явный предел и требует обязательного времени простоя (downtime) на проведение работ.
Горизонтальное масштабирование - техника, в которой мы вместо увеличения мощностей одной машины, добавляем в систему дополнительные машины, тем самым увеличивая доступные ресурсы.
Отказоустойчивость - это свойство системы, позволяющее ей не иметь единую точку отказа. Т.е. если что-то пошло не так и какая-то из машин вышла из строя, система может продолжить работу.
Лог - это упорядоченная по времени append-only структура данных.
Kafka - это распределенное, отказоустойчивое, горизонтально масштабируемое хранилище, основной структурой данных которой является append-only лог, которое поддерживает потоковую обработку данных и имеет развитую экосистему коннекторов для интеграции с базами данных и другими хранилищами.
Плюсы Kafka:
Очередь обычно используются для отложенной обработки событий или для организации буфера перед сервисами защищая их от всплесков нагрузки.
Принципиальная организация очереди:
Producer -> Server <-> Consumer
Producer отправляют запросы в именованную очередь заранее сконфигурированную на сервере.
Модели запросов Consumer'ов к серверу:
pull - consumer раз в n-секунд отправляют запрос на сервер для получения новой информации.
Плюсы: потребители сами регулируют свою нагрузку, сообщения можно объединять в группы(батч) для достижения лучшей пропускной способности.
Минусы: разбалансированность нагрузки разных consumer'ов и высокая задержка при обработке данных.
push - сервер сам посылает запросы консьюмерам (ex: RabbitMQ)
Плюсы: снижает время обработки сообщений (по сравнению с pull) и позволяет балансировать нагрузку консьюмеров
Жизненный цикл сообщение в очереди:
send - продюсер послал сообщение
fetch - консьюмер забрал сообщение (сообщению присвоен уникальный идентификатор), сервер сообщение пометил что сообщение недоступно (сообщение все еще хранится на сервере)
process - сообщение обрабатывается консьюмером, после он шлет запрос либо об удачной обработке либо об ошибке (ack/nack)
ack/nack - сервер получает сообщение от консьюмера об окончании обработки.
Если успешно - сообщение удаляется навсегда, если ошибка или таймаут - сообщение передается другому консьюмеру.
Основное отличие Kafka от очередей - сообщения НЕ УДАЛЯЮТСЯ по мере их обработки консьюмерами.
Одни и те же сообщения могут быть обработаны СКОЛЬКО УГОДНО РАЗ!
Схема кафки похожа на очередь:
Producer -> Kafka Broker <- Consumer
Структура сообщений в кафке:
{
key: "Warrning",
value:"Help me!!",
timestamp: ...,
headers: [{}, ...] - опционально (метаданные или заголовки)
}
Сообщения отправляются и хранятся в именованных топиках (Topic)
Каждый топик состоит из 1й или более партиций (Partition)
Если ключи повторяются что сообщения записываются в одну и туже партицию.
Это гарантирует порядок записи и чтения.
Каждая партиция может быть реплицирована n раз, где n - replication factor (настраивается).
Нужно для сохранности данных.
Партиция - это распределенный отказоустойчивый лог.
У каждой партиции есть 1 бокер - лидер (Leader - брокер, который работает с клиентом)
Сообщения всегда отправляются лидеру и, в общем случае, читаются с лидера.
У каждого лидера может быть 0..N фоловеров (Follower)
Каждая партиция и есть лог
Каждое новое сообщение, отправленное продюсеров в партицию, сохраняется в голову этого лога и получает уникальный монотонно возрастающий offset. Offset это 64bit число, назначаемое брокером.
Удаление сообщений происходит согласно конфигурации ренетшена (retention):
Каждый консьюмер обычно является частью консьюмер-группы или набора таких же консьюмеров.
Каждая такая группа регистрируется брокером в кластере кафки.
Данные из одного топика могут читаться множеством консьюмеров из множества групп.
Когда несколько консьюмеров читают сообщения из одного топика, то они получают сообщения из разных патриций, чтобы распределить нагрузку.
Партиции внутри группы назначаются консьюмерам уникально.
Партиция - это основной инструмент масштабирования.
Своими словами:
Кафка назначает одному консьюмеру в рамках группы одну партицию.
Если консьюмеров больше чем партиций, то консьюмеры с не назначенными партициями просто не будут использованы.
Если один их косьюмеров рухнет, то партиция будет перераспределена, и в случае наличия незадействованного консьюмера будет назначена ему. Т.о. обеспечиваем отказоустойчивость.
Если консьюмеры не справляются с объемом данных, или необходимо распределить нагрузку между брокерами - добавляем партиции в топик.
Партиции можно добавить в любой момент, но:
Для каждой группы хранится свой consumer offset для партиции, что позволяет разным группам обрабатывать сообщения независимо друг от друга с разной скорость.
Консьюмеры коммитят в брокер свой offset (т.е. записывают последнее обработанное сообщение)
При старте консьюмер запрашивают у брокера свой offset и стартуют с последнего обработанного сообщения.
Источник