Событийные системы: Kafka, RabbitMQ и очереди
События и команды, брокеры, партиции и consumer group'ы Kafka и как выбрать правильный инструмент.
За 30 секунд
В событийной системе сервисы объявляют факты («заказ оформлен»), а другие сервисы на них реагируют, вместо того чтобы вызывать друг друга напрямую. Брокер сообщений хранит и доставляет эти сообщения. Kafka — надёжный лог с возможностью повторного чтения, созданный для потоков с высокой пропускной способностью; RabbitMQ — гибкий маршрутизатор сообщений; очереди на Redis вроде BullMQ — простой вариант для фоновых задач. Правильный выбор зависит от требований к порядку, повторному чтению, пропускной способности и от того, сколько инфраструктуры вы готовы обслуживать.
Не в моём ежедневном стеке — я понимаю принципы и изучу детали, когда это понадобится проекту.
Почему это важно
- События отвязывают producer'ов от consumer'ов: оформлению заказа не нужно знать, что на заказ реагируют и лояльность, и аналитика, и рассылка писем.
- Брокер поглощает всплески трафика и сохраняет работу, когда consumer недоступен, — это делает системы гораздо устойчивее.
- Kafka важна, когда команде нужны потоки с высокой пропускной способностью, долгое хранение и повторное чтение: аналитические пайплайны, журналы аудита, change data capture, много независимых потребителей одних и тех же данных.
- Знание гарантий доставки каждого инструмента предотвращает классические баги: потерянные сообщения, дубликаты и обработку не по порядку.
Как это работает
01События, команды и брокеры
Команда просит кого-то что-то сделать: «отправь это письмо», «спиши деньги с этой карты». У неё один предполагаемый обработчик, и её можно отклонить. Событие сообщает факт, который уже произошёл: «заказ 42 оплачен». Ему всё равно, кто слушает: отреагировать могут ноль или десять потребителей. Если их путать, начинаются проблемы: «событие» с именем SendEmail привязывает producer'а к одному потребителю. Брокер сообщений — почта между ними. Producer'ы публикуют в него сообщения, он надёжно их хранит, а consumer'ы получают их в своём темпе. Если consumer лежит, сообщения ждут. Если трафик подскочил, растёт хвост очереди, а не плавится база. Цена — асинхронность: producer больше не знает, когда и выполнена ли работа вообще, поэтому нужен мониторинг хвостов и сбоев.
- Команда: повелительное наклонение, один обработчик, может провалиться («ReserveStock»).
- Событие: прошедшее время, много обработчиков, неизменяемый факт («StockReserved»).
- Брокер: надёжный буфер и маршрутизатор между producer'ами и consumer'ами.
02Kafka: topic'и, партиции, offset'ы и consumer group'ы
Kafka — распределённый лог, в который можно только дописывать. Сообщения пишутся в topic, разбитый на партиции; каждая партиция — упорядоченная последовательность, где каждое сообщение получает offset (свой порядковый номер). Сообщения с одинаковым ключом всегда попадают в одну и ту же партицию, поэтому порядок гарантирован в пределах ключа (например, ID заказа), но никогда — по всему topic'у. Consumer'ы объединяются в consumer group; Kafka назначает каждую партицию ровно одному consumer'у в группе, так что число партиций ограничивает параллелизм. Каждая группа отслеживает свои закоммиченные offset'ы, а значит, много групп (биллинг, аналитика, поиск) читают один topic независимо. Сообщения не удаляются при чтении: они хранятся определённое время или до определённого объёма либо компактируются до последнего значения по каждому ключу. Начиная с Kafka 4.0 кластеры работают на KRaft без ZooKeeper, а в Kafka 4.2 появились готовые к продакшену share group'ы для потребления в стиле очереди.
# Create a topic: 6 partitions, 3 replicas, 7-day retention
kafka-topics.sh --bootstrap-server localhost:9092 --create \
--topic orders.v1 --partitions 6 --replication-factor 3 \
--config retention.ms=604800000 --config min.insync.replicas=2
# Produce keyed messages (same key -> same partition -> ordered)
kafka-console-producer.sh --bootstrap-server localhost:9092 \
--topic orders.v1 --property parse.key=true --property key.separator=:
# Inspect a consumer group: current offset, end offset and lag per partition
kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--describe --group billing-service
03RabbitMQ и очереди на Redis
RabbitMQ — маршрутизатор сообщений. Producer'ы публикуют в exchange, который направляет сообщения в очереди через binding'и: direct (точный routing key), topic (шаблоны вроде «order.*»), fanout (во все привязанные очереди) или headers. Consumer'ы забирают сообщения из очередей и подтверждают их; неподтверждённые сообщения доставляются повторно, а отклонённые могут уйти в dead-letter exchange. После подтверждения сообщение исчезает, так что RabbitMQ — про доставку работы, а не про хранение истории (его stream-очереди добавляют режим, похожий на лог, когда нужно повторное чтение). Он хорош для маршрутизации отдельных сообщений, приоритетов и request-reply. Очереди на Redis, такие как BullMQ (Node) или очереди Laravel с драйвером Redis, — самый лёгкий вариант: задачи с повторами, backoff, задержками, rate limit'ами, задачи по расписанию и повторяющиеся задачи — всё на том Redis, который у вас, скорее всего, уже есть. Их ограничение — надёжность и масштаб: Redis держит данные в памяти, так что настройте persistence и относитесь к очереди как к исполнителю задач, а не как к постоянному хранилищу событий.
04Гарантии доставки на практике
Любой брокер предлагает какую-то комбинацию трёх гарантий. At-most-once: consumer коммитит до обработки, так что при падении сообщение теряется, но никогда не дублируется; приемлемо для метрик, редко — для бизнес-данных. At-least-once: consumer обрабатывает, затем подтверждает; падение между этими шагами означает повторную доставку, поэтому дубликаты случаются. Это реалистичный вариант по умолчанию для большинства систем. Exactly-once: каждое сообщение влияет на результат один раз. Kafka поддерживает это внутри Kafka — с помощью идемпотентных producer'ов и транзакций, когда consumer'ы читают только закоммиченные данные, — для пайплайнов read-process-write между topic'ами Kafka. Как только побочный эффект выходит за пределы Kafka (запись в базу, письмо, списание с карты), вы снова в мире at-least-once и должны сделать consumer идемпотентным: хранить ID обработанных сообщений, использовать уникальные ограничения или upsert'ы и проектировать обработчики так, чтобы их двойной запуск ничего не менял.
- Сторона producer'а: acks=all и включённая идемпотентность (по умолчанию в современных клиентах Kafka).
- Сторона consumer'а: коммитьте offset'ы после успешной обработки, а не до.
- «Ядовитые» сообщения: повтор с backoff, затем перенос в dead-letter topic или очередь.
05Схемы, версионирование и выбор инструмента
События — это публичный контракт, который часто читают команды, с которыми вы никогда не встретитесь, поэтому относитесь к их структуре как к API. Описывайте схемы в Avro, Protobuf или JSON Schema, храните их в schema registry и применяйте правила совместимости: опциональные поля добавляйте свободно, но никогда не удаляйте и не меняйте назначение поля, на которое полагаются потребители. Для ломающих изменений публикуйте новый тип события или новую версию topic'а (orders.v2) и держите обе, пока потребители не переедут. Включайте в каждое сообщение ID события, тип, версию, таймстемп и ключ сущности. Как выбирать: Kafka — для больших потоков, долгого хранения, повторного чтения и множества consumer group'ов; RabbitMQ — для гибкой маршрутизации, распределения задач и подтверждения каждого сообщения; очереди на Redis вроде BullMQ — для фоновых задач приложения с повторами и расписанием; управляемые сервисы (SQS, SNS, Pub/Sub, managed Kafka) — когда вы не хотите сами обслуживать брокеры.
Когда применять
- Многим независимым потребителям нужен один и тот же поток фактов (аналитика, индексация поиска, уведомления).
- Нужно повторное чтение: перестроение read-модели, заполнение нового сервиса или аудит истории.
- Высокая пропускная способность (от тысяч до миллионов сообщений в секунду) с порядком в пределах ключа.
- Работа должна переживать простои consumer'ов и всплески трафика, не теряя запросов.
Когда не стоит
- Одно приложение с фоновыми задачами: очередь на Redis или на базе данных проще и дешевле.
- Вызывающей стороне нужен немедленный ответ: используйте синхронный API, а события оставьте для побочных эффектов.
- Команда пока не умеет обслуживать и мониторить распределённый брокер: используйте управляемый сервис или очередь попроще.
Альтернативы
- RabbitMQ
Exchange'и и очереди с богатой маршрутизацией, подтверждениями и dead-lettering; идеален для распределения задач.
- Redis + BullMQ / очереди Laravel
Лёгкие задачи с повторами, задержками и rate limit'ами; не долгосрочный лог событий.
- Управляемые облачные очереди
SQS/SNS, Google Pub/Sub, Azure Service Bus: никаких брокеров на вашей стороне, оплата по использованию.
- NATS / Redis Streams
Лёгкий стриминг с consumer group'ами, когда Kafka слишком тяжела.
Лучшие практики
- Называйте события в прошедшем времени и держите их неизменяемыми фактами.
- Выбирайте ключи партиций по сущности, которой нужен порядок, и закладывайте число партиций с расчётом на будущих потребителей.
- Делайте каждый consumer идемпотентным; исходите из того, что любое сообщение может прийти дважды.
- Публикуйте события через transactional outbox, чтобы изменения в базе и сообщения никогда не расходились.
- Версионируйте схемы с помощью registry и проверок совместимости.
- Мониторьте consumer lag, dead-letter очереди и частоту повторов и алертите на их рост.
Частые ошибки
- Ожидать глобального порядка в Kafka: он гарантирован только внутри партиции.
- Коммитить offset'ы до обработки и терять сообщения при падении.
- Использовать брокер как базу данных со спонтанными запросами вместо нормальных read-моделей.
- Горячие партиции из-за перекошенного ключа (например, одного огромного клиента), которые ограничивают пропускную способность.
- Менять структуру события без версионирования и тихо ломать потребителей.
Глубже
06Надёжность внутри Kafka: реплики, ISR и выбор лидера
У каждой партиции есть одна реплика-лидер, принимающая записи, и фолловеры, которые её копируют. In-sync replica set (ISR) — это лидер плюс фолловеры, отстающие не больше чем на replica.lag.time.max.ms. При acks=all продюсер получает успех, только когда запись есть у всех текущих членов ISR; min.insync.replicas задаёт, до какого размера может сжаться ISR, прежде чем записи начнут отклоняться с NotEnoughReplicas. Типичная надёжная конфигурация — replication factor 3, min.insync.replicas 2 и acks=all: один брокер может упасть без потери данных и без остановки записи. Оставьте unclean.leader.election.enable в значении по умолчанию false; если его включить, лидером может стать несинхронизированная реплика и молча потерять уже подтверждённые сообщения ради доступности. Распределяйте реплики по стойкам или зонам доступности через broker.rack, чтобы отказ одной зоны не унёс все копии.
- RF 3 + min.insync.replicas 2 + acks=all: безопасно переживает потерю одного брокера.
- Идемпотентность продюсера и acks=all — значения по умолчанию в клиенте начиная с Kafka 3.0.
- Unclean election меняет подтверждённые данные на доступность; не включайте его.
07Ребалансировка, новый протокол консьюмеров и зависания обработки
Когда консьюмеры подключаются, уходят или падают, партиции перераспределяются в ходе ребалансировки. Классический протокол мог останавливать всю группу; cooperative-sticky assignment это смягчил, а протокол нового поколения (KIP-848), общедоступный начиная с Kafka 4.0, переносит назначение на group coordinator на стороне брокера и ребалансирует инкрементально. Клиенты включают его через group.protocol=consumer; группы переводятся во время rolling upgrade. Важны два таймаута. session.timeout.ms обнаруживает мёртвого консьюмера по heartbeat. max.poll.interval.ms обнаруживает зависшего: если обработчик между вызовами poll работает дольше, консьюмер исключается, его партиции переезжают, а незакоммиченный батч обрабатывается заново в другом месте. Поэтому медленные обработчики приводят к повторной работе и штормам ребалансировок. Уменьшите max.poll.records, вынесите долгую работу в отдельную очередь или ставьте партиции на паузу на время обработки.
08Компакция, retention и replay в больших масштабах
Retention может быть по времени или размеру (политика delete) или по ключу (политика compact). Компакция хранит как минимум последнюю запись для каждого ключа и в фоне удаляет более старые, превращая топик в надёжную таблицу текущего состояния: профили клиентов, цены товаров, конфигурацию. Запись с null-значением — это tombstone: она помечает ключ на удаление и сама удаляется через delete.retention.ms, поэтому консьюмеры, отставшие сильнее, могут пропустить удаления. Сочетание обеих политик хранит последнее значение по ключу и всё равно удаляет очень старые ключи. Replay — суперсила: новая consumer group, стартующая с самого раннего offset, восстанавливает read model из истории. Планируйте это: перестроение может читать терабайты, поэтому ограничивайте скорость, выделяйте ему собственную группу и убедитесь, что retention длиннее самого плохого реалистичного времени восстановления.
# A compacted topic holding the latest price per product
kafka-topics.sh --bootstrap-server localhost:9092 --create \
--topic prices.v1 --partitions 12 --replication-factor 3 \
--config cleanup.policy=compact \
--config min.compaction.lag.ms=3600000 \
--config delete.retention.ms=86400000
# Rebuild a read model: new group, start from the beginning
kafka-consumer-groups.sh --bootstrap-server localhost:9092 \
--group search-indexer-v2 --topic prices.v1 \
--reset-offsets --to-earliest --execute
09Число партиций, перекос ключей и тюнинг пропускной способности
Партиции — единица параллелизма и порядка, поэтому выбирайте их число под параллелизм консьюмеров, который ожидаете через год-два, а не сегодня: добавление партиций позже перераспределяет ключи и ломает порядок по ключу на время изменения. Слишком много партиций тоже стоит дорого: больше открытых файлов, дольше выборы лидера и больше метаданных. Ключ с намного большим трафиком, чем у остальных, создаёт горячую партицию, которую один консьюмер вынужден обрабатывать в одиночку. Исправляйте перекос более мелким ключом (order ID вместо customer ID), если порядок важен только в пределах заказа, или «солите» известный горячий ключ на несколько подключей и сливайте результат дальше по потоку. Записи без ключа распределяются sticky partitioner, который заполняет один батч и только потом переходит к следующему. На продюсере linger.ms и batch.size меняют несколько миллисекунд latency на гораздо более высокую пропускную способность, а сжатие (lz4 или zstd) снижает нагрузку на сеть и диск.
Реальные ситуации
Consumer lag растёт каждый вечер
Проблема
Аналитическая consumer group в пик отстаёт на часы и догоняет только ночью. Добавление экземпляров консьюмеров не помогло.
Как решить
Запустите kafka-consumer-groups.sh --describe, чтобы увидеть lag по партициям. Если lag сосредоточен на одной-двух партициях, причина в перекосе ключей: смените ключ или «посолите» горячий. Если он распределён равномерно, а экземпляров уже столько же, сколько партиций, лишние экземпляры простаивают, поэтому увеличьте число партиций в новой версии топика и мигрируйте или ускорьте обработчик, батча записи в базу. Проверьте циклы ребалансировки из-за обработчиков, превышающих max.poll.interval.ms. Затем настройте алерты на скорость роста lag и time-to-drain, а не на абсолютное число.
Двойные списания после падения консьюмера
Проблема
Платёжный консьюмер иногда списывает с клиента деньги дважды. Логи показывают перезапуск консьюмера между списанием и коммитом offset.
Как решить
Это at-least-once доставка, работающая как задумано; обработчик просто не идемпотентен. Дайте каждому событию стабильный ID и передавайте платёжному провайдеру производный idempotency key, чтобы повторный вызов вернул исходный результат. Записывайте ID обработанных событий в той же транзакции базы, что и изменение локального состояния, с уникальным ограничением, и пропускайте уже виденные. Держите auto-commit выключенным и коммитьте offset только после обработки. Добавьте ежедневную задачу сверки локальных платежей с отчётом провайдера, чтобы поймать всё, что проскочило.
Выбор брокера для продукта среднего размера
Проблема
Команда поддерживает одно приложение, где уже есть Redis. Им нужны события заказов для email, loyalty и будущего аналитического пайплайна, и они спрашивают, внедрять ли Kafka прямо сейчас.
Как решить
Начните с сегодняшних потребностей: несколько консьюмеров, скромный объём, требования к replay пока нет. Очередь задач на Redis для побочных эффектов, которую питает transactional outbox, закрывает это без новой инфраструктуры. Проектируйте события так, будто они публичные (ID, версии, схемы), чтобы перенос в лог позже был изменением relay, а не переписыванием. Когда аналитике или нескольким независимым командам понадобятся история и replay, подключите managed Kafka и направьте на неё outbox relay, вместо того чтобы с первого дня самим держать брокеры.
Шпаргалка
- Надёжный продюсер
acks=all, enable.idempotence=true (по умолчанию с 3.0)- Надёжный топик
--replication-factor 3 --config min.insync.replicas=2- Lag consumer group
kafka-consumer-groups.sh --bootstrap-server host:9092 --describe --group app- Replay с начала
kafka-consumer-groups.sh ... --group g --topic t --reset-offsets --to-earliest --execute- Протокол ребалансировки нового поколения (4.0+)
group.protocol=consumer- Читать только закоммиченные транзакционные данные
isolation.level=read_committed- Последнее значение по ключу
cleanup.policy=compact- Выше пропускная способность продюсера
linger.ms=10, batch.size=65536, compression.type=zstd- Чтобы обработчики не исключались
Уменьшите max.poll.records или увеличьте max.poll.interval.ms
Вопросы и ответы
Q1Kafka или RabbitMQ: как выбрать?
Я спрашиваю, для чего нужны сообщения. Если это поток фактов, который независимо потребляют несколько команд, нужны хранение и повторное чтение, а объём высокий — подходит Kafka: это надёжный лог с consumer group'ами и порядком в пределах ключа. Если это задачи, которые нужно распределять между воркерами, с правилами маршрутизации, приоритетами и подтверждением каждого сообщения, — лучше подходит RabbitMQ, и о нём проще рассуждать. Для фоновых задач внутри одного приложения часто хватает очереди на Redis вроде BullMQ. Важна и стоимость эксплуатации: управляемый вариант снимает с маленьких команд большую часть рисков.
Q2Как Kafka гарантирует порядок?
Только внутри партиции. Producer отправляет сообщения с ключом, по хэшу ключа выбирается партиция, и внутри неё сообщения сохраняют порядок и получают возрастающие offset'ы. Так что если ключом выбран ID заказа, все события одного заказа обрабатываются последовательно, а разные заказы — параллельно по разным партициям. Порядка между партициями нет. Порядок зависит и от producer'а: при включённой идемпотентности повторы не переставляют сообщения. Будьте осторожны при увеличении числа партиций: ключи могут попасть в новые партиции, и во время изменения порядок для «летящих» ключей может нарушиться.
Q3Что значит exactly-once в Kafka?
Kafka предлагает семантику exactly-once для потоков read-process-write, которые остаются внутри Kafka. Идемпотентные producer'ы не допускают дубликатов из-за повторов, а транзакции атомарно записывают выходные сообщения и offset'ы consumer'а, так что consumer, читающий с read_committed, видит каждый результат один раз. Для потоковой обработки это мощно. Но как только ваш обработчик пишет в базу, вызывает платёжный API или отправляет письмо, Kafka не может сделать этот внешний эффект exactly-once. На практике at-least-once доставку комбинируют с идемпотентными обработчиками — уникальными ключами, upsert'ами или таблицей обработанных сообщений, — чтобы получить exactly-once эффект.
Q4Что такое consumer lag и почему это важно?
Lag — разница между последним offset'ом в партиции и offset'ом, который закоммитила consumer group: сколько сообщений ждёт обработки. Это самый важный сигнал здоровья событийной системы. Растущий lag означает, что consumer'ы медленнее producer'ов — из-за бага, медленной зависимости, повторяющегося «ядовитого» сообщения или слишком малого числа consumer'ов. Поскольку одну партицию в группе читает один consumer, добавление consumer'ов сверх числа партиций не помогает. Я бы алертил на рост lag во времени, а не на фиксированное число, и смотрел бы его вместе с метриками dead-letter и доли ошибок.
Q5Как развивать схемы событий, не ломая потребителей?
Относитесь к событиям как к публичному API. Описывайте их в Avro, Protobuf или JSON Schema, регистрируйте в schema registry и включайте режим совместимости — обычно backward или full. Безопасные изменения — добавление опциональных полей со значениями по умолчанию; небезопасные — удаление, переименование или изменение смысла полей. Для ломающего изменения опубликуйте новую версию события или новый topic и держите обе, пока каждый потребитель не переедет, а затем выведите старую из оборота. Каждое сообщение должно нести свой тип и версию, чтобы потребители могли обрабатывать несколько версий во время перехода.
Q6Почему бы просто не использовать очередь на Redis для всего?
Для многих приложений — можно и нужно. BullMQ или очереди Laravel на Redis дают повторы, backoff, задержки, rate limit и расписание почти без дополнительной инфраструктуры. Ограничения появляются с ростом масштаба и потребностью в истории: Redis держит данные в памяти, persistence нужно аккуратно настраивать, задачи удаляются после выполнения, а встроенного повторного чтения для нового потребителя, которому нужны события за прошлый месяц, нет. Когда нескольким командам независимо нужен один и тот же поток или нужны долгое хранение и очень высокая пропускная способность, лог вроде Kafka становится лучшим инструментом. Выбирайте по потребности, а не по моде.
Вопросы уровня senior
S1Как гарантировать порядок по каждой сущности и при этом ретраить упавшие сообщения?
Порядок и ретраи конфликтуют: если сообщение 5 по заказу упало, а вы пошли дальше, сообщение 6 применится первым. Варианты по степени строгости. Блокировать партицию и ретраить на месте с backoff: порядок сохраняется, но одно «ядовитое» сообщение останавливает все ключи этой партиции, поэтому ограничьте число попыток и настройте алерт. Использовать retry-топик на каждый уровень задержки, но заодно «парковать» последующие сообщения того же ключа, пока упавшее не пройдёт, — для этого нужно небольшое per-key хранилище состояния. Или проектировать обработчики устойчивыми к беспорядку через версии: каждое событие несёт версию сущности, а консьюмер игнорирует всё, что старше сохранённого. Последний вариант лучше масштабируется и переживает replay, поэтому я предпочитаю делать изменения состояния проверяемыми по версии и идемпотентными, а строгую блокировку оставляю только для немногих потоков, которым она действительно нужна.
S2Своя Kafka или managed-сервис: что вы взвешиваете?
Хорошо эксплуатировать Kafka — значит планировать мощности брокеров и дисков, делать rolling upgrade, перераспределять партиции, настраивать rack-aware репликацию, мониторить under-replicated партиции и здоровье контроллера, плюс безопасность с TLS и ACL. Для этого нужны реальная экспертиза и время на on-call. Managed-сервис снимает большую часть этого, часто добавляет tiered storage и автоскейлинг, а платите вы более высоким счётом за единицу пропускной способности, некоторым lock-in по инструментам и меньшим контролем над версиями и тюнингом. Для команды без выделенных платформенных инженеров managed почти всегда дешевле, если учесть зарплаты. Self-hosting начинает иметь смысл при больших стабильных объёмах, строгих правилах размещения данных или когда платформенная команда уже эксплуатирует похожие stateful-системы. В любом случае держите клиентов на стандартных протоколах Kafka, чтобы переезд оставался возможным.
S3Event sourcing на Kafka: хорошая идея или нет?
Kafka отлично подходит для распространения событий, но как основное хранилище для event-sourced агрегатов она слаба. Event sourcing требует быстро загружать все события одной сущности и дописывать, только если сущность всё ещё в ожидаемой версии, — это проверка optimistic concurrency. В Kafka нет ни чтения по сущности, поскольку топики разбиты по ключу на множество сущностей, ни условного дописывания. Команды, которые пробуют это, в итоге строят отдельное хранилище снапшотов и борются с race condition. Лучший дизайн хранит event store в базе данных или специализированном event store с версионированием по потоку, а затем публикует эти события в Kafka через outbox или change data capture для других консьюмеров. Тогда Kafka делает то, в чём она хороша: fan-out, retention и replay для проекций.
Глоссарий
- Партиция
- Упорядоченная часть топика, в которую можно только дописывать; единица порядка и параллелизма.
- Offset
- Порядковый номер записи внутри партиции.
- Consumer group
- Набор консьюмеров, делящих партиции топика, со своими закоммиченными offset.
- ISR
- In-sync replicas: лидер и фолловеры, отстающие настолько мало, что учитываются для acks=all.
- Ребалансировка
- Перераспределение партиций между консьюмерами группы при изменении её состава.
- Log compaction
- Хранение как минимум последней записи по каждому ключу с удалением старых версий.
- Tombstone
- Запись с null-значением, помечающая ключ на удаление в компактированном топике.
- KRaft
- Встроенный кворум метаданных Kafka на базе Raft; единственный режим с тех пор, как Kafka 4.0 убрала ZooKeeper.
- Dead-letter topic
- Куда попадают сообщения после повторных ошибок обработки — для разбора и повторного проигрывания.
Что изучить дальше
Есть идея продукта?Давайте создадим его.
Расскажите о своей идее, продукте или команде. Обычно отвечаю в течение одного рабочего дня.