Потоковая обработка
Windowing и время
Твиттер хочет показать trending topics за последние 15 минут, обновляя каждую минуту. Биржа считает объём торгов поминутно. Аналитика показывает сессии пользователей. Три разные задачи - три разных типа окон. А мобильное приложение шлёт события с задержкой до 2 минут из-за плохого соединения - нужны watermarks. Windowing - это то, как бесконечный поток превращается в конечные агрегаты.
- **Twitter Trending** - sliding window 15 минут / slide 1 минута поверх Kafka; hashtag trending = count за скользящее окно; ~500M твитов в день через Storm/Heron
- **Биржа NYSE** - tumbling window 1 минута для OHLCV (Open/High/Low/Close/Volume); 4 млрд событий в день; event time критичен для корректных свечей
- **Google Analytics** - session windows с gap 30 минут; сессия пользователя = все события до 30-минутного перерыва; watermark 4 часа для mobile (offline события)
Tumbling Windows
Биржа хочет знать суммарный объём торгов **за каждую минуту** - строго с 10:00 до 10:01, с 10:01 до 10:02, без пересечений. Это tumbling window: поток делится на непересекающиеся отрезки одинаковой длины. Каждое событие попадает ровно в одно окно.
**Tumbling window** - окна фиксированного размера без пересечений. Параметр один: размер (length). Пример: 5-минутные tumbling windows - [0:00-5:00), [5:00-10:00), [10:00-15:00). Простой случай для count, sum, avg за фиксированные периоды.
Tumbling window 1 час настроен в Flink. Событие с event time 10:59:59 пришло в обработку в 11:02:00. В какое окно оно попадёт?
Sliding Windows
Мониторинг серверов показывает среднее CPU за **последние 5 минут, обновляясь каждую минуту**. В 10:01 показывает среднее [09:56-10:01), в 10:02 - [09:57-10:02). Это sliding window: окна перекрываются. Одно событие может попасть сразу в несколько окон.
**Sliding window** (hopping window) - два параметра: **size** (ширина окна) и **slide** (шаг сдвига). Если slide < size - окна перекрываются. Одно событие входит в `ceil(size/slide)` окон одновременно. Стандарт для moving average, rate-of-change, trending topics.
Sliding window size=10мин, slide=2мин. В сколько окон одновременно попадает одно событие?
Session Windows
Аналитика поведения пользователя: сколько страниц просматривается за одну «сессию»? Сессия заканчивается, если пользователь не активен 30 минут. Ширина окна неизвестна заранее - зависит от поведения. Это **session window**: границы определяются активностью, а не фиксированным временем.
**Session window** - динамические окна, разделённые периодами неактивности. Параметр: **session gap** (таймаут). События внутри одной «сессии» объединяются в одно окно. Как только пауза между событиями превышает gap - старое окно закрывается, новое начинается при следующем событии.
Session window с gap 10 минут. Пользователь кликает в 10:00, 10:08, 10:25, 10:30. Сколько сессий образуется?
Watermarks
Событие с event time 10:04:55 приходит в 10:06:30 - на 95 секунд позже. Flink уже закрыл окно [10:00-10:05) и выдал результат в 10:05:00? Или ждёт опоздавших? **Watermark** отвечает на вопрос: «в какой момент мы уверены, что все события до времени T уже получены».
**Watermark W(t)** - утверждение: «все события с event time <= t уже обработаны». Flink закрывает окно [start, end) когда W(t) >= end. Стратегия **BoundedOutOfOrderness**: watermark = max_seen_event_time - max_out_of_orderness. Если max_out_of_orderness = 30 сек, Flink ждёт опоздавших до 30 секунд.
Watermark - это просто задержка обработки: чем больше watermark, тем медленнее система
Watermark - trade-off между корректностью и задержкой результата. Большой watermark = дольше ждём опоздавших = результат приходит позже, но корректнее. Маленький watermark = быстрый результат, но опоздавшие события будут отброшены или обработаны в sideOutput.
Netflix использует watermark 30 секунд для mobile-событий (телефон мог быть в туннеле). Финансовые системы - watermark 2-5 секунд (надёжная сеть, строгие latency требования). Batch-replay через Kafka использует monotonous watermarks (порядок гарантирован) для максимальной скорости.
Watermark strategy настроена с maxOutOfOrderness = 60 секунд. Последнее событие имело timestamp 10:10:00. Какой watermark будет опубликован?
Ключевые идеи
- **Tumbling** - непересекающиеся окна фиксированного размера; каждое событие в одном окне; для биржевых свечей, почасовых агрегатов
- **Sliding** - перекрывающиеся окна (size > slide); одно событие в N=size/slide окнах; для moving average, trending topics
- **Session** - динамические окна по активности; gap = таймаут неактивности; для пользовательских сессий, кластеризации событий
- **Watermark W(t)** - утверждение «все события до t уже получены»; BoundedOutOfOrderness = max_event_time - delay; окно закрывается когда W >= window_end
Связанные темы
Windowing - основной инструмент агрегации в потоковых системах:
- Apache Flink: внутреннее устройство — Checkpointing и state backends - инфраструктура для надёжного windowing
- Stream Processing основы — Event time vs processing time - фундаментальный выбор перед настройкой окон
Вопросы для размышления
- Twitter показывает trending topics за 15 минут, обновляя каждую минуту. Это sliding window (size=15мин, slide=1мин). Каждый твит попадает в 15 окон одновременно. Как это влияет на нагрузку на state backend по сравнению с tumbling(15мин)?
- Watermark 30 секунд значит: результат окна [10:00-10:05) появится только в 10:05:30. Для финансового мониторинга это слишком долго - нужен watermark 2 секунды. Но мобильный клиент может задержать событие на 90 секунд. Как сбалансировать через allowedLateness и sideOutputLateData?
- Session windows с gap 30 минут для 10 миллионов пользователей. Каждая активная сессия требует буферизации событий до закрытия. Что происходит с состоянием Flink если 1 миллион пользователей одновременно в активной сессии - почему RocksDB state backend критичен?