NATS или Apache Kafka: что выгоднее и когда
Когда в проекте появляется первая очередь сообщений или шина событий, почти всегда встает вопрос: ставить тяжелую Kafka «на вырост» или обойтись легким NATS и не тратить память впустую. Ответ зависит не от моды, а от того, что вы реально гоняете — телеметрию с IoT-датчиков, события микросервисов или журнал транзакций, который нельзя терять и нужно перечитывать через полгода. Разберем оба брокера по архитектуре, ресурсам и типовым сценариям, чтобы вы выбирали осознанно, а не по инерции «все ставят Kafka».
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Что это вообще такое: два разных инструмента
NATS и Kafka решают на первый взгляд одну задачу — передачу сообщений между сервисами, но выросли из разных идей.
NATS изначально проектировался как простая, быстрая шина publish-subscribe: сервер написан на Go, стартует за секунды, потребляет десятки мегабайт памяти в простое. Базовый режим — «at most once», сообщения не сохраняются на диск, если подписчика нет онлайн — сообщение теряется. Для durable-очередей и персистентности есть надстройка JetStream (с 2021 года часть ядра NATS), которая добавляет хранение на диске, повторную доставку, потоки (streams) и consumer group-подобную модель.
Kafka изначально строилась как распределенный commit log для LinkedIn — с расчетом на терабайты данных в сутки, партиционирование, репликацию и долгое хранение (retention). Это JVM-приложение, которое до недавнего времени обязательно требовало ZooKeeper; начиная с версии 3.x доступен режим KRaft без ZooKeeper, который стал дефолтным в Kafka 4.0. Kafka по умолчанию пишет всё на диск и хранит журнал заданное время (или до заданного объема), независимо от того, прочитал ли кто-то сообщение.
Разница в философии: NATS — это скорее «нервная система» приложения для событий здесь и сейчас, Kafka — это журнал истины, который можно перечитать заново.
Архитектура и модель доставки
NATS Core — простой pub/sub без гарантий доставки: сообщение уходит подписчикам, которые сейчас слушают тему (subject). Нет подписчика — сообщение исчезает. Плюс — минимальная задержка, сервер почти не тратит CPU на маршрутизацию.
NATS JetStream добавляет поверх этого:
- потоки (streams) — сообщения сохраняются на диске или в памяти с настраиваемым retention (по времени, по количеству, по размеру);
- consumers — durable и ephemeral, с ack/nack, redelivery, приоритетами;
- репликацию потока между узлами кластера (R1/R3/R5).
Пример создания потока через nats CLI:
nats stream add ORDERS \
--subjects "orders.>" \
--storage file \
--retention limits \
--max-age 24h \
--replicas 3
Kafka организована вокруг топиков, разбитых на партиции. Каждая партиция — упорядоченный неизменяемый лог, продюсеры пишут в конец, консьюмеры читают с произвольным offset и сами решают, что перечитывать. Партиции реплицируются между брокерами (обычно replication.factor=3), лидер партиции обрабатывает запись, реплики синхронизируются.
Пример топика:
kafka-topics.sh --create --topic orders \
--partitions 12 \
--replication-factor 3 \
--config retention.ms=604800000 \
--bootstrap-server broker1:9092
Ключевое отличие для проектирования системы: в Kafka порядок гарантирован только внутри партиции, и число партиций — это одновременно и единица параллелизма для консьюмеров. В NATS JetStream порядок гарантирован внутри потока, консьюмеры могут быть как push, так и pull, с более гибкой маршрутизацией по wildcard-темам (orders.*.created).
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверПроизводительность и потребление ресурсов
Здесь разница ощутима на практике, а не только в бенчмарках вендоров.
NATS-сервер — один бинарник на Go без внешних зависимостей. На тестовом VPS с 2 vCPU / 4 GB RAM голый NATS Core стартует и держит десятки тысяч соединений при памяти в районе 50-150 МБ. С включенным JetStream и активным хранением на диске память растет пропорционально числу потоков и размеру буферов, но конфигурация из коробки остается компактной.
Kafka — это JVM-процесс, и меньше 1 GB heap ему выделять не имеет смысла: для тестового кластера типичный старт — -Xms1g -Xmx1g, для продакшена рекомендуют от 4-6 GB heap плюс еще столько же ОС оставляет под page cache, потому что Kafka активно полагается на файловый кеш для чтения свежих сообщений. Плюс отдельный процесс (ZooKeeper, если вы еще на нём, или встроенный KRaft-контроллер), диски под сегменты лога.
Точные цифры пропускной способности сильно зависят от размера сообщений, числа партиций/consumers, настроек acks, сети и диска — не берите чужие бенчмарки как истину, тестируйте на своей нагрузке. Ориентировочно: NATS Core выигрывает по задержке (доли миллисекунд) и по накладным расходам на маленькое сообщение, а Kafka с батчингом (linger.ms, batch.size) вытягивает более высокий суммарный throughput на больших объемах данных за счет последовательной записи на диск и сжатия батчей.
Практический вывод для аренды сервера: под NATS достаточно 2-4 vCPU / 4-8 GB RAM даже под приличную нагрузку, под Kafka с 3 брокерами и репликацией разумный старт — 3 отдельных сервера от 4 vCPU / 8 GB RAM каждый плюс SSD с запасом под retention.
Persistence, durability и retention
В NATS JetStream хранение настраивается по потоку: --storage file пишет на диск с fsync, --storage memory держит в оперативной памяти (быстрее, но переживает только рестарт процесса, не падение узла). Retention — limits (по возрасту/размеру), interest (пока есть хоть один consumer) или workqueue (сообщение удаляется после успешного ack хотя бы одним consumer). Это гибко, но по умолчанию рассчитано на «рабочую очередь», а не на долгосрочный архив событий.
Kafka хранит журнал по умолчанию бессрочно (пока хватает места) или по retention.ms/retention.bytes, и явно поддерживает сценарий «читать историю с начала» — новый консьюмер может подключиться и перечитать данные за последние N дней. Отдельно есть log.cleanup.policy=compact, которая держит только последнее значение по ключу (полезно для CDC и снапшотов состояния).
Если ваша задача — event sourcing, аудит, восстановление состояния сервиса перечитыванием истории событий, Kafka спроектирована под это нативно. Если задача — доставить команду или уведомление и забыть про него после обработки, JetStream с workqueue retention справится проще и с меньшими накладными расходами.
Репликация в обоих случаях защищает от потери узла, но не от потери данных на уровне приложения — бэкапы дисков и снапшоты все равно нужны отдельно. Для дисков под очереди пригодится тот же подход, что и для баз данных — см. мониторинг диска на VPS, чтобы не словить ENOSPC посреди ночи.
Развертывание и эксплуатация
NATS ставится буднично — один бинарник, один конфиг-файл, systemd-юнит. Пример минимального конфига с JetStream:
# /etc/nats/nats-server.conf
port: 4222
http_port: 8222
jetstream {
store_dir: /var/lib/nats/jetstream
max_mem: 1G
max_file: 20G
}
cluster {
name: prod
listen: 0.0.0.0:6222
routes: [
nats-route://node2:6222
nats-route://node3:6222
]
}
Готовую пошаговую установку с systemd и TLS смотрите в статье NATS на Ubuntu 24.04: пошаговая установка, а типовые проблемы после запуска — в разборе частых ошибок NATS на сервере.
Kafka эксплуатационно тяжелее: нужно продумать число брокеров (минимум 3 для продакшен-репликации), синхронизировать версии Java, настроить server.properties под KRaft-режим, следить за ребалансировкой партиций при добавлении брокеров, мониторить lag консьюмеров и состояние ISR (in-sync replicas). Апгрейды версий Kafka исторически требуют аккуратности — несовместимость протокола между мажорными версиями бывает болезненной.
Для обоих брокеров критично настроить мониторинг заранее, а не когда очередь встала колом — связка Prometheus + Grafana подходит и туда, и туда, экспортеры есть под оба брокера (kafka-exporter, встроенные /varz и /healthz у NATS). Если у вас еще не поднят стек мониторинга — начните с Prometheus и Grafana: пошаговая установка.
Сравнение в цифрах и параметрах
| Параметр | NATS (JetStream) | Apache Kafka |
|---|---|---|
| Язык / рантайм | Go, один бинарник | JVM |
| Старт под нагрузку | 1 сервер, минуты | 3+ брокера, часы на настройку |
| Минимум ресурсов (продакшен) | ~2 vCPU / 4 GB RAM | 3× (4 vCPU / 8 GB RAM+) |
| Задержка на маленьких сообщениях | доли мс | мс, зависит от batching |
| Долгий retention/replay истории | ограниченно (workqueue/limits) | нативно, до бессрочного |
| Партиционирование/consumer groups | consumers по потоку, гибче | партиции топика, строже |
| Порог входа в эксплуатацию | низкий | средний-высокий |
| Экосистема (Kafka Connect, коннекторы к БД/CDC) | скромнее | огромная |
| Zero external deps | да | KRaft убрал ZooKeeper, но JVM остается |
Цифры по ресурсам — ориентир для типовой нагрузки на старте, не гарантированный SLA: под вашу конкретную схему сообщений и retention значения могут отличаться в разы, тестируйте на копии прод-трафика перед финальным выбором железа.
Когда выбирать что: практические сценарии
Берите NATS, если:
- нужна быстрая шина событий между микросервисами внутри одного продукта (RPC-подобные запросы, request-reply через NATS Core);
- телеметрия с IoT/edge-устройств, где важна низкая задержка и простота развертывания на скромном железе;
- команда небольшая, нет отдельного DevOps на full-time поддержку Kafka-кластера;
- сообщения — команды и уведомления, которые не нужно хранить неделями и перечитывать с нуля.
Берите Kafka, если:
- нужен полноценный event sourcing или CDC (Change Data Capture) с Debezium — экосистема Kafka Connect закрывает это из коробки;
- объемы данных растут в терабайты, и важна гарантированная упорядоченность внутри ключа с высоким суммарным throughput;
- несколько независимых команд/сервисов должны читать один и тот же поток событий с разной скоростью и с возможностью перечитать историю;
- у вас уже есть Kafka-экосистема (Kafka Streams, ksqlDB, Connect) или это требование заказчика/архитектуры.
Промежуточный вариант, который часто упускают: можно использовать NATS JetStream для internal-шины между сервисами одного продукта и держать Kafka отдельно как «шину интеграции» между разными командами и системами — они не взаимоисключающие, а решают разные слои архитектуры.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Можно ли мигрировать с Kafka на NATS без потери функциональности?
Частично — если вы не используете Kafka Connect, Kafka Streams или compaction по ключу как основной паттерн, JetStream закроет базовый pub/sub и durable-очереди. Event sourcing с глубоким replay истории на NATS реализовать сложнее.
NATS вообще как-то реплицируется на несколько дата-центров?
Да, есть режим leaf nodes и gateway-соединения между кластерами для мульти-региональных топологий, но это отдельная настройка поверх обычного кластера, не «из коробки» одной галочкой.
Kafka обязательно требует ZooKeeper?
Нет, начиная с Kafka 3.3 режим KRaft (без ZooKeeper) считается production-ready, а с Kafka 4.0 стал дефолтным. На старых инсталляциях ZooKeeper еще встречается, но для новых проектов есть смысл сразу ставить KRaft.
Хватит ли одного VPS под Kafka для теста?
Да, для разработки и локальных тестов один брокер с replication.factor=1 запускается и на одном сервере от 4 GB RAM. Для продакшена с отказоустойчивостью нужно минимум 3 отдельных узла.
NATS теряет сообщения при рестарте сервера?
NATS Core — да, если нет активных подписчиков. JetStream с --storage file и репликацией переживает рестарт и падение отдельного узла кластера, данные остаются на диске остальных реплик.
Что проще мониторить в проде?
NATS проще: встроенный HTTP-эндпоинт /varz, /healthz, /jsz отдает состояние без доп. настройки. Для Kafka обычно ставят отдельный kafka-exporter и следят за десятками метрик (ISR, under-replicated partitions, consumer lag) — порог входа в мониторинг выше.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →