«Правильное» время в системах потоковой аналитики
Сегодня поговорим об одной концепции, которая распространена в разных фреймворках обработки данных и является очень важной для дата-инженеров, разрабатывающих системы потоковой аналитики.
Рассмотрим практический пример
У вас есть приложение (назовем его SaleWatch), которое считает, сколько заказов сделали пользователи на сайте в режиме реального времени. Данные поступают к вам потоком (например, через топик Apache Kafka), и ваше приложение разбивает этот поток на окна по 5 минут, считая сумму совершённых заказов за каждый интервал. Зачем? Например, по этой метрике можно будет понять, что произошел отказ сервиса, даже если технические метрики этого не покажут.
В 13:00 ваше приложение даёт сбой, падает и продолжает «лежать» на протяжении 3 часов (до 16:00), а данные в это время накапливались в очереди сообщений Kafka. Возникает проблема: если сейчас запустить приложение, то оно быстро считает накопившиеся данные из кафки, просуммирует, и на выходе метрика будет выглядеть так, словно все заказы за последние три часа были совершены за 5 минут с 16:00 до 16:05.
Как этого избежать?
Для решения проблемы нужно воспользоваться «альтернативным режимом времени» — event time. Давайте выясним, что это значит. Во многих фреймворках (включая такие распространенные, как Apache Spark и Apache Flink) есть два режима времени: 1. Processing Time — когда система обрабатывает отдельное событие, она опирается на текущее время, которое можно узнать у операционной системы. 2. Event Time — когда система обрабатывает событие, она опирается на время, указанное в самом событии (например, в поле timestamp).
Что это значит на практике:
- Если наше приложение SaleWatch работает в режиме processing time, то действительно оно будет думать, что все события, накопившиеся в очереди, появились только что, в момент их прихода. Оно положит их в первое же пятиминутное окно, и мы получим неправильную сумму (все заказы за три часа, когда приложение лежало, окажутся в показателях за первую пятиминутку с 16:00 до 16:05).
- Если наше приложение работает в режиме event time, то оно по времени событий поймет, что они относятся к предыдущим часам, когда оно лежало, распределит их по нужным окнам и посчитает по ним суммы корректно.
Почему бы всегда не использовать event time?
К сожалению, такая точность не достаётся бесплатно. Приложения в режиме event time потребляют больше ресурсов, чем в режиме processing time. Поэтому включать event time стоит только в тех приложениях, для которых точность критична.
У вас мог возникнуть вопрос — как же приложение в режиме event time понимает, что все данные пришли и можно закрывать окно, если оно не знает о реальном времени? Для этого используется механизм, называемый watermarks. О нём мы поговорим в следующих заметках.
Полезные ссылки: 1. Event time в документации Apache Flink 2. Event time в документации Apache Spark