Flink の基礎#
内容参考自:
有状態ストリーム処理#
概念#
従来のバッチ処理:データを継続的に収集し、時間を基準にバッチを区切り、定期的にバッチ計算を実行する。このような場合に考えられるシナリオの問題:
- 1 時間を 1 つのバッチの基準とした場合、特定のイベントの変換回数を統計する必要がある。変換が 58 分に始まり、次の時間の 7 分に終了する場合、どのようにしてバッチを跨いだデータ統計を行うのか?
- データが生成されてから受信されるまでの間にかかる時間は一定ではなく、あるイベントが A よりも早く発生したが、A よりも遅く到着した場合、このような受信時間の順序が逆転する問題をどのように処理するのか?
理想的な方法は:
状態(State)
メカニズムを導入し、状態を蓄積し維持する。蓄積された状態は過去の歴史の中で受け取ったすべての歴史的イベントを表し、出力結果に影響を与える。Time時間メカニズム
: データの完全性を操作するメカニズムがあり、特定の時間帯のデータがすべて受信された後にのみ出力結果を計算する。
これがいわゆる有状態ストリーム処理である。
有状態ストリーム処理の課題#
- 状態フォールトトレランス (State Fault Tolerance):
- 状態管理 (State Management):
- イベント時間処理 (Event-time processing):
- 状態保存と移行 (Savepoints and Job Migration):
状態フォールトトレランス#
シンプルなシナリオの正確に 1 回 (Exactly-once) フォールトトレランス保証:
無限ストリームのデータが入ってくるが、後ろは単一のプロセス計算である。この場合、プロセスが正確に 1 回の状態フォールトトレランスを確保するためには、各データを処理した後、状態を変更した後にスナップショットを行う。スナップショットはキューに含まれ、対応する状態と比較され、一致するスナップショットが完成すれば、正確に 1 回を確保できる。
分散状態フォールトトレランス#
-
分散シナリオでは、複数のノードが計算を行い、ローカル状態を変更するが、1 つの
Global consistent snapshot
(全域一致性スナップショット) のみを生成する。 -
checkpoint
チェックポイントメカニズムに基づいてフォールトトレランス回復を行う。 -
simple lamport
アルゴリズムメカニズムに基づく拡張実装分散スナップショット
、Flink は計算を中断することなくGlobal consistent snapshot
(全域一致性スナップショット) を継続的に完成させることができる。大まかな方法は、Flink がデータストリームにチェックポイントバリアフラグを挿入し、以降のオペレーターがデータストリームでチェックポイントバリア N を受信すると、自分の状態を保存する。このようにして、最初のデータソースから計算完了後まで、このチェックポイント保存状態が確立され、以降にもチェックポイントバリア N+1、N+2 がデータストリームで同期して行われるため、運算を妨げることなく継続的にチェックポイントを生成することができる。
状態管理#
Flink が現在サポートしている方法は:
-
JVM Heapストレージ状態
: 状態量が少ない場合に適している。なぜなら、直接 JVM ヒープに保存され、状態を読み取る必要があるときは、Java オブジェクトを使用して直接読み書きするため、シリアル化は不要である。しかし、チェックポイントが各計算値のローカル状態を分散スナップショットに入れる必要がある場合は、シリアル化が必要になる。 -
RocksDBストレージ状態
: 一種のアウトオブコア状態バックエンド。ランタイムのローカル状態バックエンドでユーザーが状態を読み取る際にはディスクを経由するため、状態をディスクに維持することになる。それに伴うコストは、状態を読み取るたびにシリアル化とデシリアル化のプロセスを経る必要があるため、性能は相対的に劣る可能性がある。
イベント時間処理#
処理時間(Processing Time)
: プロセスタイムはイベントが到着してから処理を開始する時間であり、必ずしも一定ではない。例えば、ネットワークの理由でこの時間が変わることがある。イベント時間(Event Time)
: イベント時間はイベントが実際に発生した時間であり、各処理記録が持つタイムスタンプに基づいて判断される。これは唯一で不変である。接入時間(Ingestion Time)
: イベントがソースオペレーターで Flink データストリームに入る時間を指す。
対比
- 処理時間は扱いやすいが、イベント時間はより複雑である。
- 処理時間を使用する場合、得られる処理結果(またはストリーム処理アプリケーションの内部状態)は不確定である。一方、Flink 内部でイベント時間に対してさまざまな保障が行われているため、イベント時間を使用する場合、データを何度再生しても相対的に確定的で再現可能な結果が得られる。
- 処理時間を使用すべきかイベント時間を使用すべきかを判断する際には、ある原則に従うことができる:アプリケーションが前のチェックポイントまたはセーブポイントから再生する必要がある場合、結果が完全に同じであることを望むかどうか。結果が完全に同じであることを望む場合は、イベント時間を使用するしかない。結果が異なることを受け入れる場合は、処理時間を使用できる。処理時間の一般的な用途は、現実の時間に基づいてシステム全体のスループットを統計することであり、例えば現実の時間で 1 時間に処理されたデータの数を計算する場合、この状況では処理時間を使用するしかない。
参考リンク
状態保存と移行#
Savepoint メカニズムに基づいて実現され、Savepoint はチェックポイントに似ているが、異なる点は Savepoint は手動でトリガーされ、全体の状態保存に使用される。具体的な参考リンク:
Flink リアルタイム計算 - チェックポイントとセーブポイントの深い理解
Flink 基本概念#
-
Streams
: ストリームは有限データストリームと無限データストリームに分かれ、unbounded stream
は始まりも終わりもないデータストリーム、すなわち無限データストリームである。一方、bounded stream
はサイズが制限された始まりと終わりのあるデータ集合、すなわち有限データストリームであり、両者の違いは無限データストリームのデータは時間の推移とともに増加し続け、計算が継続し、終了状態が存在しないのに対し、有限データストリームはデータサイズが固定され、計算が最終的に完了し、終了状態にあることである。 -
State
: 状態は計算過程におけるデータ情報であり、フォールトトレランス回復とチェックポイントにおいて重要な役割を果たす。ストリーム計算は本質的にインクリメンタル処理であるため、状態を保持するために継続的にクエリを行う必要がある。また、正確に 1 回のセマンティクスを確保するためには、データが状態に書き込まれる必要がある。さらに、永続的なストレージは、分散システム全体が失敗またはクラッシュした場合でも正確に 1 回を保証することができ、これは状態のもう一つの価値である。 -
Time
:Event time
、Ingestion time
、Processing time
に分かれ、Flink の無限データストリームは継続的なプロセスであり、時間はビジネスの状態が遅れているか、データ処理がタイムリーであるかを判断するための重要な基準である。 -
API
: API は通常 3 層に分かれ、上から下に分けるとSQL / Table API
、DataStream API
、ProcessFunction
の 3 層である。API の表現能力とビジネス抽象能力は非常に強力であるが、SQL 層に近づくにつれて表現能力は徐々に弱まり、抽象能力は強化される。逆に、ProcessFunction 層の API の表現能力は非常に強力であり、さまざまな柔軟で便利な操作を行うことができるが、抽象能力は相対的に小さくなる。
Flink ウィンドウ#
- イベント数に基づくカウントウィンドウ
- セッション間隔に基づくセッションウィンドウ
- 時間に基づくタイムウィンドウ