Этот материал — обзор открытой практики, а не кейс KT.Team. Мы разбираем, какой бизнес-результат даёт Apache Kafka в обработке заказа, опираясь на публичные источники: инженерные публикации Confluent о Walmart и общепринятый паттерн распределённых транзакций Saga.
Какую проблему решает единый поток событий
Классическая боль интернет-магазина и омниканального ритейла — рассинхрон остатков. Витрина, склад (WMS), маркетплейсы и ERP держат своё представление о наличии товара и обмениваются данными пакетной выгрузкой раз в N минут или часов. Результат: товар продан в двух каналах одновременно (oversell), покупатель оплатил отсутствующую позицию, операторы вручную сверяют выгрузки и отменяют заказы. Чем больше каналов и SKU, тем дороже эта ручная сверка и тем выше доля отменённых заказов.
Apache Kafka меняет модель обмена. Вместо того чтобы периодически спрашивать «сколько сейчас на складе?», системы публикуют факты-события в общий лог: `OrderCreated`, `InventoryReserved`, `PaymentProcessed`, `OrderShipped`. Каждое событие сохраняется в durable-логе, читается несколькими потребителями независимо и в любой момент может быть переигран. Заказ перестаёт быть строкой в базе одной системы и становится потоком событий, который сам ведёт себя по этапам.
Как событие заказа запускает резерв, оплату и доставку
Базовый сценарий описан и в материалах Confluent, и в публикациях по durable-оркестрации (Kai Waehner): событие `OrderPlaced` запускает цепочку «проверить остаток → зарезервировать оплату → передать в доставку». Реализуют это двумя способами.
Хореография (choreography). Центрального координатора нет. Сервис заказов публикует `OrderCreated`. Сервис склада подписан на этот топик, проверяет и резервирует позицию, публикует `InventoryReserved`. Платёжный сервис, поймав резерв, списывает деньги и публикует `PaymentProcessed`. Доставка подписана на оплату и создаёт отгрузку. Каждый сервис деплоится и масштабируется отдельно, зная только про события, а не про соседей.
Оркестрация (orchestration) / Saga. Отдельный оркестратор ведёт состояние заказа и явно вызывает шаги. Это паттерн Saga: распределённая транзакция как последовательность локальных транзакций, каждая из которых публикует событие для следующей. Ключевая часть — компенсирующие транзакции: если оплата не прошла, система автоматически отменяет заказ и снимает резерв со склада. Компенсации обязаны быть идемпотентными и безопасными к повтору — это прямое следствие гарантий доставки Kafka и наличия DLQ для сбойных сообщений.
Главный выигрыш: остаток уменьшается в момент резерва, а не при ночной выгрузке. Все каналы читают один и тот же поток, поэтому oversell и ручная сверка между витриной, складом и ERP исчезают как класс.
Открытый пример: Walmart
Walmart публично описал событийную систему учёта остатков на Apache Kafka. По данным инженерного блога Confluent, цель — поддерживать «актуальный снимок позиции по каждому товару» во всех физических магазинах и онлайн-каналах. Система собирает данные более чем из 10 источников событий с разными схемами и приводит их к каноническому виду «умным» движком трансформации, использует Kafka Streams для обработки и Apache Cassandra для хранения.
Инженеры отдельно описали продакшен-настройки, которые делают поток надёжным: согласование числа потребителей с числом партиций, `acks=1` для баланса надёжности и пропускной способности, выравнивание партиций Kafka и Cassandra, гарантия «одна пара товар-магазин обрабатывается ровно одним потребителем» — это и обеспечивает консистентность данных без блокировок. По оценкам из публикаций Confluent, в смежной системе пополнения Walmart обрабатывает десятки миллиардов сообщений из около 100 млн SKU менее чем за три часа при пропускной способности порядка 85 ГБ/мин.
Это иллюстрация архитектурного принципа, а не рекламы конкретного вендора: тот же подход воспроизводим на открытом Apache Kafka без проприетарных надстроек.
Принципы, которые делают решение отчуждаемым
С точки зрения инженерной зрелости здесь работают международные стандарты, а не самописные костыли. Контракты событий стоит зафиксировать в schema registry, чтобы команды витрины, склада и доставки развивались независимо и не ломали друг друга. Изменения состояния из старых систем (ERP, WMS) заводят в поток через CDC (change data capture) — это позволяет внедрять Kafka рядом с легаси, не переписывая ядро. Идемпотентность потребителей и DLQ — обязательная часть, а не опция.
Такой контур получается слабосвязанным и отчуждаемым: каждый сервис заменяем, поток событий — общий язык между командами и подрядчиками, а ядро торговой платформы остаётся немодифицированным.
Схема процесса
Слева направо: Витрина / маркетплейсы публикуют `OrderCreated` в Kafka. Топик заказа читают параллельно три потребителя — Склад (резерв остатка → `InventoryReserved`), Оплата (списание → `PaymentProcessed`), Доставка (отгрузка → `OrderShipped`). Снизу к шине через CDC подключены ERP и WMS как источники и приёмники остатков. Пунктиром показан обратный поток компенсаций: при `PaymentFailed` оркестратор публикует `ReleaseReservation` и `OrderCancelled`, возвращая остаток. Единый лог = единый источник правды по остаткам для всех каналов.
Бизнес-итог процесса
Перевод обработки заказа на единый поток событий Kafka даёт измеримый результат: резерв остатка происходит в реальном времени, а не по ночной выгрузке; oversell и двойные продажи между каналами устраняются; ручная сверка витрины, склада и ERP заменяется автоматической компенсацией сбойных заказов. Бизнес получает корректные остатки во всех каналах одновременно и сокращает долю отмен — при этом ядро торговой платформы остаётся немодифицированным, а сервисы и команды — взаимозаменяемыми.