Короче говоря, лучшее решение - использовать DoFn с сохранением состояния в Beam. Вы можете иметь состояние для каждого ключа (и для каждого окна, которое в вашем случае является глобальным окном). Вы можете сохранить события одного потока в состоянии, и как только события из другого потока появятся с тем же ключом, присоедините его к событиям в состоянии. Вот ссылка [1].
Однако, короткий ответ не использует истинную силу модели Луча. Модель Beam предоставляет способы баланса между задержкой, стоимостью и точностью. Предоставляет простой API, чтобы скрыть сложную потоковую обработку.
Почему я это говорю? Давайте вернемся к решению краткого ответа: с состоянием DoFn. В подходе DoFn с учетом состояния вам не хватает способов ответить на следующие вопросы:
- Что если вы буферизировали события 1M для одного ключа, и в другом потоке события по-прежнему не появлялись? Вам нужно опустошить государство? Что если событие появится сразу после опустошения штата?
- Если в конце концов есть одно событие, которое, по-видимому, завершает JOIN, приемлема ли стоимость буферизации 1M событий для JOIN одного события из другого потока?
- Как обработать позднюю дату в обоих потоках? Скажем, вы присоединились к
<1, a>
из левого потока <1, b> из правого потока. Позже есть еще один <1, c>
из левого потока, откуда вы знаете, что вам нужно только испустить <1, <c, b>>
, предположим, что это инкрементный режим для вывода результата. Если вы начинаете буферизовать те уже присоединенные события, чтобы получить дельту, это действительно становится слишком сложным для программиста.
Управление лучами, управление триггерами, уточнение выходных данных, управление водяными знаками и задержкой SLA предназначены для того, чтобы скрыть от вас следующие сложности:
- водяной знак: указывает, когда окна завершены, так что события не будут продолжаться долго (и дальнейшие события будут рассматриваться как поздние данные)
- Lateness SLA control: контролируйте время, когда вы кэшируете данные для объединения.
- уточнение выходных данных: корректно обновлять вывод, если разрешены новые события.
Хотя модель Beam хорошо спроектирована. В реализации модели Beam отсутствуют важные функции для поддержки описанного вами объединения:
- Оконное управление недостаточно гибкое, чтобы поддерживать ваш случай, когда потоки имеют огромные разные частоты (поэтому фиксированное и скользящее окно не подходит). Кроме того, вы также не знаете частоту поступления потоков (поэтому окно сеанса на самом деле не подходит, так как вы должны задать промежуток между окнами сеанса).
- отсутствует ретракция, так что вы не можете уточнить вывод, как только появятся поздние события.
В заключение, модель Beam разработана для обработки сложных потоковых данных, которые идеально соответствуют вашим потребностям. Но реализация недостаточно хороша, чтобы позволить вам использовать ее сейчас, чтобы завершить ваш вариант использования соединения.
[1] https://beam.apache.org/blog/2017/02/13/stateful-processing.html