В распределенных системах и микросервисах брокеры сообщений играют важную роль. Они обеспечивают асинхронную связь, разделяют сервисы и повышают надежность и масштабируемость. Современная архитектура в значительной степени зависит от брокеров сообщений, что делает их ключевым компонентом во многих шаблонах проектирования.
Kafka и RabbitMQ — два самых популярных брокера сообщений. Они известны своей надежностью, эффективностью и адаптивностью, отличной документацией, поддержкой и сообществами.
RabbitMQ — это бесплатное решение с открытым исходным кодом, имеющее двойную лицензию Apache License 2.0 и Mozilla Public License 2. Оно позволяет использовать и изменять его по мере необходимости. Оно функционирует как чистый брокер сообщений, поддерживая несколько протоколов и предлагая дополнительные функции.
Kafka, также с открытым исходным кодом под лицензией Apache 2.0, — это больше, чем просто брокер сообщений; это распределенная платформа потоковой передачи событий. Она предоставляет расширенные функции, включая Kafka Streams.
При сравнении RabbitMQ и Kafka не существует «лучшего» решения; речь идет о поиске наиболее подходящего для вашей архитектуры и целей решения.
Эта статья проведет вас через ключевые функции и характеристики, сравнивая их напрямую. Она направлена на то, чтобы предоставить всестороннее понимание различий между Kafka и RabbitMQ, помогая вам сделать осознанный выбор на основе вашей конкретной проблемы и требований.
RabbitMQ поддерживает различные протоколы, такие как:
С другой стороны, Kafka использует свой двоичный протокол на основе TCP, оптимизированный для высокой пропускной способности, и полагается на абстракцию «набора сообщений». Эта абстракция позволяет сетевым запросам группировать сообщения вместе, сокращая накладные расходы на сетевые циклы за счет отправки пакетов вместо отдельных сообщений. Пользовательский протокол Kafka обеспечивает гибкость в разработке и оптимизации для сценариев с высокой нагрузкой.
Однако у пользовательского протокола есть и недостатки. Он изолирует Kafka от других брокеров сообщений, что приводит к отсутствию взаимодействия. В отличие от RabbitMQ, который совместим с любым клиентом AMQP, Kafka требует использования клиентов Kafka. Тем не менее, благодаря популярности Kafka и усилиям сообщества, клиенты Kafka доступны для многих языков программирования.
Подходы к маршрутизации в RabbitMQ и Kafka существенно различаются.
Основные компоненты маршрутизации RabbitMQ:
Прежде чем углубляться в тему бирж, следует прояснить еще два понятия:
Существует четыре типа обмена:
*(звездочка) соответствует ровно одному слову.
#(хеш) соответствует нулю или более слов.
Например, очередь, связанная с ключом маршрутизации "apple.*.banana", будет получать сообщения с ключами типа "apple.orange.banana" или "apple.strawberry.banana" . Очередь, связанная с #.banana, будет получать сообщения с ключами типа "apple.banana" или "apple.orange.banana".
Маршрутизация Кафки проще. Основные компоненты:
По сравнению с RabbitMQ возможности маршрутизации Kafka ограничены. Он не предназначен для гранулярной маршрутизации, а для высокой производительности и масштабирования.
Здесь следует отметить одну важную вещь:
В RabbitMQ, когда Потребитель получает сообщение из Очереди, он «крадет» его. Если подтверждение успешно получено, другие Потребители не получат сообщение. Потребители Kafka ведут себя так же, если они находятся в одной и той же Группе Потребителей. Группа Потребителей — это абстракция Kafka, которая позволяет нескольким Потребителям читать из одной и той же Темы независимо, гарантируя, что каждая Группа Потребителей обрабатывает все сообщения Темы.
В RabbitMQ долговечность и устойчивость являются отдельными характеристиками:
Долговечность. Это свойство очередей и обменов. Существует два типа очередей: прочные и временные. Прочная очередь (или обмен) хранит свои метаданные на диске и может пережить перезапуск брокера. Временные очереди этого не делают.
Сохранение. Устойчивая очередь не гарантирует сохранность сообщения. Чтобы сделать ее устойчивой, необходимо настроить сохранение. Когда издатель отправляет сообщение, он может указать свойство сохранения. В этом случае сообщение будет сохранено во внутреннем дисковом хранилище и будет доступно после перезапуска брокера.
Kafka хранит все на диске. В отличие от RabbitMQ, который удаляет сообщения после подтверждения Consumer, Kafka сохраняет все сообщения до тех пор, пока они не достигнут предела времени жизни (TTL) или размера диска. Это позволяет повторно обрабатывать сообщения другой или той же Consumer Group.
И RabbitMQ, и Kafka поддерживают кластеризацию, при которой несколько брокеров работают вместе.
В RabbitMQ кластеризация улучшает доступность и обеспечивает безопасность данных. Если говорить о производительности, то вертикальное масштабирование является предпочтительным способом повышения производительности RabbitMQ. Горизонтальное масштабирование может добавить значительные накладные расходы на синхронизацию. Обычно вы бы предпочли иметь кластер из 3 брокеров, чтобы обеспечить доступность в случае отказа одного брокера.
RabbitMQ не поддерживает разделение очередей по умолчанию, но стоит отметить, что оно у него есть.
Kafka эффективно масштабируется. Он не только обеспечивает доступность и безопасность данных, но и повышает производительность обработки данных. Ключевая концепция здесь — разбиение на разделы. Каждая тема имеет настраиваемое количество разделов. Каждый раздел работает изолированно от других, выступая в качестве физического хранилища и обработки данных. Вы можете реплицировать каждый раздел по всему кластеру, что обеспечивает отказоустойчивость. Производители и потребители работают только с основным (или первичным) разделом. Если брокер с этим разделом выходит из строя, система выбирает новый первичный раздел из реплик.
Выбор правильного количества разделов имеет решающее значение. Большое количество разделов замедляет восстановление системы в случае отказа узла. И наоборот, это ограничивает пропускную способность и уровень параллелизма для группы потребителей. В пределах одной группы потребителей каждый раздел может работать только с одним потребителем (что фактически является одним потоком в вашем приложении). Поэтому наличие трех разделов не имеет смысла, если у вас больше трех потребителей, поскольку остальные будут простаивать.
RabbitMQ гарантирует упорядочение в пределах одной очереди. Один потребитель будет обрабатывать сообщения по порядку. Однако ситуация меняется с несколькими потребителями. Если один потребитель выходит из строя, система возвращает неподтвержденные сообщения в очередь, но следующий потребитель может уже обрабатывать следующую партию. Итак, какие есть варианты?
RabbitMQ и Kafka предоставляют гарантии доставки «по крайней мере один раз», то есть дубликаты возможны, но сообщения будут полностью обработаны по крайней мере один раз.
У Kafka есть дополнительные возможности доставки:
Как уже упоминалось ранее, отказываясь от гибкости маршрутизации, Kafka взамен приносит мощные функции.
Kafka предлагает мощные библиотеки потоковой обработки:
С помощью Kafka Streams вы можете выполнять агрегацию данных по времени по вашей теме и передавать результаты в другую тему или базу данных.
Предположим, у вас есть тема с курсами обмена валют по разным валютным парам, и вы хотите объединить данные графика открытия-максимума-минимума-закрытия (также OHLC) за определенные периоды времени (5 минут, 30 минут, 1 час и т. д.).
Один из вариантов — хранить данные в базе данных временных рядов, которая подходит для такой обработки. Однако, если у вас есть Kafka, это вам не нужно. Используя простые агрегации Kafka Stream, вы можете вычислять данные OHLC поверх темы Kafka и помещать результаты в любую базу данных для дальнейшего запроса.
Kafka также позволяет вам представлять обработанные сообщения в виде таблицы. Он помещает результаты агрегации в абстракцию таблицы, к которой вы можете получить доступ через KSQL. Такое состояние таблицы является долговечным. Если брокер перезапустится, он восстановит последнее состояние из соответствующей темы.
Как мы видим, Kafka выходит за рамки базовой функциональности брокера сообщений и вступает на территорию обработки в реальном времени и ETL.
Kafka и RabbitMQ — отличные инструменты для сценариев с высокой пропускной способностью и низкой задержкой. Выбор зависит от особенностей варианта использования, архитектуры и будущих требований. Например, Kafka идеально подходит для долгосрочного хранения событий транзакций, тогда как RabbitMQ отлично подходит для сценариев, требующих совместимости протоколов и гибкости маршрутизации. Когда и RabbitMQ, и Kafka подходят, подумайте о своих будущих потребностях.