В прошлых уроках мы разобрались с batch и streaming как самостоятельными шаблонами. Реальная жизнь сложнее: компании часто хотят и точность batch, и низкую латентность streaming, и иногда — оба сразу. Два классических архитектурных шаблона пытаются решить эту задачу: Lambda Architecture и Kappa Architecture. Имена немного маркетинговые, но за ними стоят реальные подходы.
Lambda Architecture
Lambda Architecture придумал Nathan Marz, автор Apache Storm, в районе 2011 года. Идея — построить систему, в которой одни и те же данные обрабатываются двумя путями параллельно:
- Batch layer — медленный, точный, обрабатывает всё с самого начала. Раз в день/час пересчитывает агрегаты.
- Speed layer — быстрый, приблизительный, обрабатывает только последние события. Покрывает gap между концом batch-окна и текущим моментом.
- Serving layer — объединяет результаты обоих слоёв и отдаёт ответ на запрос.
Одни и те же события идут в две параллельные обработки. Batch медленный и точный, speed быстрый и приблизительный. Запросы получают комбинированный результат.
Простой пример: считаем количество уникальных посетителей сайта за всё время.
- Batch считает точное число за прошедшие сутки и предыдущие. Использует обычный
COUNT(DISTINCT user_id). - Speed считает приблизительное число для сегодняшнего дня через HyperLogLog (вероятностная структура, погрешность 1-2%).
- Serving на запрос «сколько уникальных за месяц» возвращает batch (вчерашний день и раньше) + speed (сегодня).
К следующему утру batch догонит и пересчитает «сегодня» точно — речь о небольшой временной погрешности.
Зачем Lambda появилась
Lambda появилась в эпоху, когда streaming-системы были молодыми и не очень надёжными. Storm 2011 года не давал exactly-once. Watermarks были экзотикой. Чтобы получить гарантированно точный исторический результат, приходилось дублировать обработку: streaming для скорости, batch для точности.
К тому же batch-инструменты (Hadoop MapReduce, Hive) и streaming-инструменты (Storm, Trident) жили в разных экосистемах. Один и тот же job требовал двух разных реализаций кода — одной для batch, другой для streaming.
Проблемы Lambda
Lambda — это не идеальное решение. У неё есть жёсткие минусы:
Двойная кодовая база. Логика «посчитать DAU» пишется и для batch (Spark), и для speed (Storm). Это две разные кодовые базы, и они должны давать одинаковый результат. На практике расхождения неизбежны — то баг в одной версии, то изменение требования внесли только в одну ветку.
Двойная инфраструктура. Поддерживать кластер Hadoop/Spark + кластер Storm/Kafka Streams — это удвоенные операционные расходы. Два мониторинга, два набора алертов, два on-call ротации.
Сложность serving layer. Объединять batch view и real-time view с правильной логикой переходов — нетривиальная задача. Где граница? Что делать, если real-time view ещё не догнал batch? Что если они расходятся?
Сложность тестирования. Тесты приходится писать на обе ветки. Контроль качества дороже.
К 2015 году большинство команд, работавших с Lambda, сходились во мнении: это работает, но больно. Появился запрос на упрощение.
Lambda Architecture часто называют «архитектурным анти-паттерном 2020-х». Это преувеличение — в специфических сценариях она оправдана. Но как дефолтный подход для новых проектов её действительно стараются избегать.
Kappa Architecture
Kappa Architecture предложил Jay Kreps (создатель Kafka) в 2014 году в посте «Questioning the Lambda Architecture». Идея радикально проще: только streaming, никакого batch.
Все события записываются в распределённый append-only лог (Kafka). Этот лог хранит всю историю и работает как единственный источник истины. Все обработки — streaming-job-ы, которые читают из лога и пишут в свои витрины.
Если нужно пересчитать что-то по-новому или исправить баг — поднимается новая версия job-а, которая читает лог с начала и переписывает витрину. Это и есть batch — но реализованный через тот же самый streaming-движок, просто на исторических данных из лога.
Все события идут в Kafka, оттуда читаются streaming-обработчиками. Для backfill — переподписка с начала лога и перезапись витрины.
Ключевое требование Kappa — долгое хранение лога. Kafka должен держать события не сутки, а недели или месяцы, чтобы переподписка с начала имела смысл. Это решается infinite retention в Kafka или архивацией старых сегментов в S3 + tiered storage.
Преимущества Kappa
Одна кодовая база. Нет дублирования между batch и speed. Логика один раз — работает и для realtime, и для backfill.
Одна инфраструктура. Только Kafka + streaming-кластер. Никаких параллельных Hadoop-кластеров.
Простой serving layer. Витрины пишутся только из streaming. Запросы читают одну витрину, без merge.
Естественный replay. Хочешь пересчитать — подними новый job, прочитай лог с offset 0. Это и есть «батч», но без отдельного механизма.
Когда Kappa не работает
Kappa не панацея. Есть сценарии, где она проигрывает:
Очень тяжёлые исторические расчёты. Если backfill требует прогнать через streaming-движок 10 терабайт данных, это может быть в разы дороже, чем тот же расчёт в Spark batch. Streaming-движки оптимизированы под низкую латентность, не под throughput.
Источники, которые в Kafka не лежат. Если данные приходят из OLTP-баз через batch-экспорт раз в сутки, тут уже streaming не помогает. Можно сделать CDC (Debezium), но это усложнение архитектуры.
Очень сложные исторические join-ы. Streaming-join за месяц данных требует много state. Batch с разогретой машиной справится быстрее.
В таких случаях команды строят гибрид: основная обработка по Kappa-логике, отдельные тяжёлые batch-job-ы для специфических задач.
Что выбирать в 2026
Реальная картина:
- Новые проекты в облаке. Чаще выбирают Kappa-подобную архитектуру: Kafka + Flink/Spark Structured Streaming. Backfill через replay.
- Гибрид Kappa + batch. Streaming для realtime-сценариев (фрод, алерты, метрики), batch для тяжёлой аналитики. Это не Lambda — кодовые базы не дублируются.
- Pure batch. Если бизнес-требования не требуют realtime, нет смысла усложнять. Просто Spark/dbt по расписанию.
- Pure Lambda. Редко в новых проектах. Чаще как legacy с 2010-х.
Самый частый шаблон 2026 года — не Lambda и не строгий Kappa, а streaming-first архитектура с batch-fallback: основная обработка через Flink/Spark Structured Streaming, но тяжёлые исторические job-ы делают на batch-кластере. При этом кодовая база унифицирована через Spark Structured Streaming, который умеет работать в обоих режимах с одним и тем же кодом.
Попробуй сам
Подумай, как бы ты построил аналитику для онлайн-кинотеатра. Какие сценарии требуют realtime (рекомендации, антифрод, операционные алерты)? Какие — batch (биллинг, отчёты, ML-обучение)? Если выбираешь Lambda — какие проблемы это создаст? Если Kappa — какой retention нужен в Kafka? Это упражнение — типичный диалог DE на собеседовании.