case-kの備忘録

日々の備忘録です。データ分析とか基盤系に興味あります。

Dataflowでしかできないことってなんだろう。BigQueryだけじゃだめなのかな。

最近ストリーミングデータの連携基盤を作っており、パイプラインを作る過程である疑問が浮かびました。

Dataflow必要なのかな。BigQueryでも良い気がする

そこでDataflowがなかった場合、どうなるのか考えてみました。

データパイプライン

次のようなデータパイプラインを想定してます。

  • fluentd→Cloud Pub/Sub→Dataflow→BigQuery
Dataflowの役割

Dataflowの役割としては次のことを想定してます。

  • メッセージ重複排除
  • ウィンドウ処理による特徴量生成

フルマネージドな環境でマイクロバッチのようにBigQueryにデータを入れる前にデータを加工します。

これBigQueryだけでもできるんじゃないかな

改めて感じたのが、メッセージ重複やウィンドウ処理ってBigQueryでもできるよなあってことです。
メッセージの重複排除やウィンドウ処理はBigQueryで重複を排除するViewを作れば良い気がします。

BigQueryよりDataflowが優れていること

BigQueryと比較して、Dataflowを使った場合何が良いのか考えてみました。

  • リアルタイム性の向上

BigQueryにウィンドウ処理やメッセージ重複を排除するビューを作ることもできますが、データがBigQueryに到着してからビューで頻繁にクエリを実行する場合、リアルタイム性が損なわれます。
リアルタイム性をあげるために、マイクロバッチで定期的にパーティションテーブルに対し、クエリを実行して別テーブルに書き込めば計算にかかる時間は短縮されますが、それであればフルマネージドなDataflowを使った方が良いと思いました。

  • 計算コストの削減

BigQueryにウィンドウ処理やメッセージ重複を排除するビューを作ることもできますが、データがBigQueryに到着してからビューで頻繁にクエリを実行する場合、計算コストがかかります。
計算コストを抑えるために、マイクロバッチで定期的にパーティションテーブルに対し、クエリを実行し別のテーブルに書き込めば計算コストを抑えることができますが、それであればフルマネージドなDataflowを使った方が良いと思いました。

  • 遅延データの扱い

要件にもよりますが、Dataflowはウィンドウを超えて遅延データが到着した場合、再度トリガーを実行し、データの更新を行うようなことができます。速さと正確さがトレードオフであるストリーミング処理と相性が良いと思いました。
Beam Programming Guide

  • セッションウィンドウ

時間ではなく、ユーザの行動に基づいてウィンドウを分けるセッションウィンドウはBigQueryではできないように思います。セッションウィンドウは行動が類似するユーザをグルーピングでき、平均セッション時間などを求めることができます。

「We can use the session-windowed data to determine the average length of uninterrupted play time for all of our users, as well as the total score they achieve during each session. We can do this in the code by first applying session windows, summing the score per user and session, and then using a transform to calculate the length of each individual session:」
https://beam.apache.org/get-started/mobile-gaming-example/

Dataflowが解決するストリーミング処理の課題と基盤構築で考慮すること - case-kの備忘録

  • Cloud Pub/Subのat least onceによるメッセージの重複排除

Cloud Pub/Subはat least onceを採用しており、複数回メッセージを送信する。DataflowはCloud PubSubで自動付与されたメッセージI'dを考慮して自動的に重複を排除している。
Pub/Sub を使用したストリーミング  |  Cloud Dataflow  |  Google Cloud

  • Publisherが付与したメッセージIDの重複j排除

Publisherが複数回Publishした場合も想定して、DataflowではユニークなメッセージIDの重複を排除する機能があります。
Deduplicate Pub/Sub messages with Dataflow in a Spring Cloud Stream application
PubsubIO.Read (Apache Beam 2.9.0-SNAPSHOT)

DataflowはPythonをサポートしてるので、Pythonのライブラリとかデータ分析用のコードを転用できるのは良いと思いました。Pythonでループさせて並列処理で高速化をしている場合、Dataflowの方が良いと思います。

  • 動的に出力先のテーブルを変える

テーブル名など入力値によって、出力先のテーブルを分けることが可能です。(Javaのみサポート)
Google BigQuery I/O connector

  • ウィンドウ処理が苦手

BigQueryにもウィンドウ関数は用意されています。ただし、特定IDの時系列での移動平均をとりたい場合や特定IDの1ヶ月間の統計量を撮りたい場合
どうしてもループ処理が使いたくなるように思います。このような場合Dataflowの方が適しているように思います。
BigQueryのウィンドウ処理 - case-kの備忘録


結論

結論としては

ストリーミング処理はDataflowを使った方が良さそう。

って感じですかね。Dataflow使わなくても大体のことはできるけど、大変そうな気がしました。
Dataflow フルマネージドなマイクロバッチ実行環境で、計算コストを削減し、リアルタイム性を向上させることがでます。また、ウィンドウを超えて送られてきた遅延データを考慮して反映できるので、ストリーミング処理と相性の良いツールだと思いました。SQLライクであれば、ビューを作って都度都度クエリを実行し、メッセージ重複排除やウィンドウ処理による統計値を出すことができるとは思いますが、

BigQueryだとDataflowと比べて計算コストがかかり、リアルタイム性が損なわれる

ように思います。このあたりの面倒を吸収してくれるのがDataflowな気がします。
ただ、バッチのETLであればリアルタイム性は求められず、一度の実行で済むので計算コストも問題にならないように思います。

バッチのETLはBigQueryで良さそう

だと思いました。こちらの記事にもあるようにSQL中心のアーキテクチャは学習コストも少ないので良いと思います。
https://qiita.com/munaita_/items/7b666903a08e6b2543cb
バッチなど、分析用のコードなどをPythonで書いてるなら、Dataflowを使った方が良いと思うので現状の環境を考慮して決めていく感じかと思いました。