Flink 詳細説明 (2): コアパート I
14. Flink の 4 つの基礎石は何ですか?
Flink の 4 つの基礎は次のとおりです。
- チェックポイント_
- 状態_
- 時間_
- 窓_
15. Flink ウィンドウと分割メカニズムについて話します。
ウィンドウの概念:無制限のストリームデータを時間間隔に応じて複数のデータに分割し、個別に統計(集計)を実行します。
Flink は、ウィンドウを分割する 2 つの方法 (time
とcount
) をサポートしています。1 つ目は時間駆動型で除算され、もう 1 つはデータ駆動型で除算されます。
- 時間駆動のタイム ウィンドウは、タンブリングウィンドウとスライディングウィンドウに分けることができます。
- データによって駆動されるカウント ウィンドウは、タンブリングウィンドウとスライディングウィンドウに分割することもできます。
- Flink は、ウィンドウの 2 つの重要な属性 (ウィンドウの長さ
size
とスライド間隔interval
) をサポートし、ウィンドウの長さとスライド間隔によってローリング ウィンドウとスライディング ウィンドウを区別します。- サイズ = 間隔の場合、タンブリング ウィンドウ (重複するデータなし) が形成されます - ローリング ウィンドウ
- サイズ (1 分) > 間隔 (30 秒) の場合、スライディング ウィンドウ (データが重複する) が形成されます - スライディング ウィンドウ
以下の 4 つの基本ウィンドウを組み合わせて取得できます。
(1)時間ベースのローリング ウィンドウ:time-tumbling-window
データが重複しない時間ウィンドウ、設定方法の例: timeWindow(Time.seconds(5))
。
(2)時間ベースのスライディング ウィンドウ:time-sliding-window
データが重複する時間ウィンドウ、設定方法の例: timeWindow(Time.seconds(10), Time.seconds(5))
。
注: 上の図には小さなエラーがあります。これは であるはずなのでsize > interval
、重複するデータが存在します。
(3)数量ベースのローリング ウィンドウ:count-tumbling-window
データが重複しない数量ウィンドウ、設定方法の例: countWindow(5)
。
(4)数量に基づくスライディングウィンドウ:count-sliding-window
データが重複する数量ウィンドウ、設定方法の例countWindow(10,5)
:
Flink は、セッション ウィンドウSessionWindowsという特別なウィンドウもサポートしています。
セッション ウィンドウ アロケータは、セッション アクティビティを通じて要素をグループ化します。ローリング ウィンドウやスライディング ウィンドウと比較して、セッション ウィンドウには、開始時刻と終了時刻が重複せず、固定されています。
セッション ウィンドウが一定期間要素を受信しなくなった場合、つまり非アクティブ期間が発生した場合、ウィンドウは閉じられます。
セッション ウィンドウは、非アクティブ期間の長さを定義するセッション間隔によって構成されます。この非アクティブ期間が発生すると、現在のセッションが閉じられ、次の図に示すように、後続の要素が新しいセッション ウィンドウに割り当てられます。 :
16. Flink のウィンドウ メカニズムと各コンポーネントがどのように連携するかを紹介します。
以下はウィンドウメカニズムのフローチャートです:
WindowAssigner
1. ウィンドウ オペレーターはウィンドウの処理を担当し、データ フローが継続的にオペレーター (Window Operator) に入力されると、到着した各要素が最初に WindowAssigner に渡されます。WindowAssigner は、要素がどのウィンドウ (Windows) に配置されるかを決定し、場合によっては新しいウィンドウを作成します。要素は複数のウィンドウに配置できるため (個人的な理解ではスライディング ウィンドウですが、ローリング ウィンドウではこの現象は発生しません)、同時に複数のウィンドウを持つことが可能です。Window 自体は単なる ID 識別子であり、TimeWindow の開始時間と終了時間などの一部のメタデータがその中に保存される場合がありますが、ウィンドウ内の要素は保存されないことに注意してください。ウィンドウ内の要素は実際にはキー/値状態に格納され、キーはウィンドウ、値は要素のコレクション (または集計値) です。ウィンドウの耐障害性を確保するために、この実装は Flink の状態メカニズムに依存しています。
ウィンドウトリガー
2. 各ウィンドウには独自のトリガーがあり、トリガーにはタイマーがあり、いつウィンドウを計算またはクリアできるかを決定します。要素がウィンドウに追加されるか、以前に登録されたタイマーがタイムアウトになるたびに、トリガーが呼び出されます。トリガーの戻り結果は次のようになります。
- 続行(何もせずに続行)
- 火災(トリガー計算、プロセスウィンドウデータ)
- パージ (クリーニングをトリガーし、ウィンドウとウィンドウ内のデータを削除します)
- Fire + Purge (計算とパージをトリガーし、データを処理し、ウィンドウとウィンドウ内のデータを削除します)
データが到着したら、Trigger を呼び出して、計算をトリガーする必要があるかどうかを決定します。呼び出しの結果が Fire のみの場合、ウィンドウが計算され、ウィンドウはそのまま維持されます。ウィンドウ内のデータはクリーンアップされず、次のトリガーファイアが発生したときに計算が再度実行されます。ウィンドウ内のデータは、トリガ結果がクリアされるまで繰り返し計算されます。ウィンドウとデータはクリーンアップされるまで解放されないため、ウィンドウは常にメモリを占有します。
トリガートリガー処理
3. Trigger Fire がアクティブになると、ウィンドウ内の要素のコレクションが Evictor に渡されます (指定されている場合)。Evictor は主に、ウィンドウ内の要素のリストを走査し、最初にウィンドウに入った要素の数を削除する必要があるかを決定するために使用されます。残りの要素は、ウィンドウ計算のためにユーザー指定の関数に渡されます。Evictor がない場合、ウィンドウ内のすべての要素は計算のために関数に渡されます。
4. 計算関数はウィンドウの要素 (Evictor によってフィルタリングされる可能性があります) を受け取り、ウィンドウの結果値を計算し、それをダウンストリームに送信します。ウィンドウの結果値は 1 つ以上になります。DataStream API では、事前定義されたsum()
、 、min()
、max()
、ReduceFunction
などFoldFunction
、さまざまなタイプの計算関数を受け取ることができますWindowFunction
。WindowFunction
最も一般的な計算関数であり、他の定義済み関数も基本的にこの関数をベースに実装されます。
sum
5. Flink は、一部の集計ウィンドウ計算 ( 、など)min
を最適化します。これは、集計計算ではウィンドウ内のすべてのデータを保存する必要がなく、1 つのresult
値のみを保存する必要があるためです。ウィンドウに入る各要素は集約関数を 1 回実行し、result
値を変更します。これにより、メモリ消費量が大幅に削減され、パフォーマンスが向上します。ただし、ユーザーが Evictor を定義した場合、集計ウィンドウの最適化は有効になりません。これは、Evictor がウィンドウ内のすべての要素を走査する必要があり、ウィンドウ内のすべての要素を保存する必要があるためです。
17. フリンクの時間の概念について話します。
Flink のストリーム処理には、さまざまな時間の概念が関係しており、次の図に示すように、主に 3 つの時間メカニズムに分かれています。
- EventTime、イベント時間
- イベントが発生すると、たとえば、Web サイト上のリンクがクリックされたとき、各ログに独自の生成時間が記録されます。
- タイム ウィンドウが EventTime に基づいて定義されている場合、EventTimeWindow が形成され、メッセージ自体に EventTime が含まれる必要があります。
- IngestionTime、摂取時間
- Flink ノードのソース オペレーターがデータを受信する時間など、データが Flink に入力される時間 (たとえば、Kafka のソースによって消費されるデータ)。
- タイム ウィンドウが IngestionTime に基づいて定義されている場合、ソースの systemTime に基づく IngestionTimeWindow が形成されます。
- ProcessingTime、処理時間
- Flink ノードが操作を実行する時刻。たとえば、timeWindow がデータを処理するシステム時刻。デフォルトの時間属性は処理時間です。
- タイム ウィンドウが ProcessingTime ベンチマークに基づいて定義されている場合、ProcessingTimeWindow が形成され、オペレーターの systemTime が優先されます。
Flink のストリーム処理では、ほとんどのビジネスで EventTime が使用されますが、通常は EventTime が使用できない場合にのみ、ProcessingTime または IngestionTime の使用が強制されます。
18. APIを呼び出すときはどのように使えばよいですか?
final StreamExecutionEnvironment env
= StreamExecutionEnvironment.getExecutionEnvironrnent();
// 使用处理时间
env.setStreamTimeCharacteristic(TimeCharacteristic.ProcessingTime) ;
// 使用摄入时间
env.setStrearnTimeCharacteristic(TimeCharacteristic.IngestionTime);
// 使用事件时间
env.setStrearnTimeCharacteristic(TimeCharacteri stic Eve~tTime);
19. ストリーミングデータ処理において、データの遅延などの問題とその対処方法に遭遇したことはありますか?
データ遅延の問題が発生しました。例えば:
ケース 1 :
- 地下駐車場に行く途中で、携帯電話でテイクアウトを注文したいとします。
- テイクアウトを選んだ後、オンライン決済機能で支払いをしますが、この時点で11時50分です。ちょうどそのとき、地下駐車場に入ると、ここには携帯電話の電波がありません。そのため、フードデリバリーのオンライン支払いはすぐには成功せず、支払いシステムは再試行で「支払い」操作を再試行しています。
- 車を見つけて地下駐車場から出る頃には、すでに12時5分になっています。この時、再び携帯電話に信号があり、携帯電話の決済データが持ち帰りオンライン決済システムに無事送信され、決済が完了する。
- 上記のシナリオでは、支払いデータのイベント時刻が 11:50、支払いデータの処理時間が 12:05 であることがわかります。
ケース 2 :
- 上の図に示すように、アプリはユーザーのすべてのクリック動作を記録し、ログを返します (ネットワークが良好でない場合は、最初にログをローカルに保存し、後で送り返します)。
- ユーザー A は 11:02 にアプリを操作し、ユーザー B は 11:03 にアプリを操作します。
- ただし、ユーザー A のネットワークが不安定で、返信ログが遅れたため、サーバー側ではまずユーザー B からのメッセージを 11:03 に受信し、次にユーザー A からのメッセージを 11 時に受信します。 02. メッセージの順序が乱れています。
一般に、データ遅延やメッセージの順序の乱れなどの問題は、WaterMark 透かしを使用して処理されます。ウォーターマークは、データの遅延やデータの順序の乱れなどの問題を解決するために使用されます。その概要を次の図に示します。
ウォーターマークはタイムスタンプ ( timestamp
) であり、Flink はデータ ストリームにウォーターマークを追加できます。
- ウォーターマークは、元の EventTime イベント時間には影響しません。
- ウォーターマークがデータ ストリームに追加されると、ウォーターマーク時間に従ってウィンドウ計算がトリガーされます。つまり、WaterMark ウォーターマークを使用してウィンドウ計算がトリガーされます。
- ウォーターマーク時間を設定します。これはイベント時間より数秒短く、最大許容データ遅延の長さを示します。
- ウォーターマーク時間 = イベント時間 - 許容遅延時間 (例: 10:09:57 = 10:10:00 - 3 秒)
20. WaterMark の原理を説明してください。
以下に示すように:
ウィンドウは 10 分ごとにトリガーされます。現在、12:00 ~ 12:10 の間にウィンドウがあります。当初、データは 12:00 ~ 12:10 の間のこのウィンドウで計算されていましたが、遅延のため、到着しました。 12:12 現時点では、12:00 - 12:10 このウィンドウは閉じられ、データは計算のために次のウィンドウにのみ送信されるため、データの遅延が発生し、不正確な計算が発生します。
ここでウォーターマークを追加します。データのタイムスタンプは 2 分です。この時点で、データ 12:12 で生成されたイベント時刻 - 2 分の遅延を許容するウォーターマーク = 12:10 >= ウィンドウ終了時刻。ウィンドウが計算をトリガーし、データがこのウィンドウに計算されます。
DataStream API の TimestampAssigner インターフェイスを使用して、タイムスタンプの抽出動作を定義します。これには 2 つのサブインターフェイスAssignerWithPeriodicWatermarks
インターフェイスとAssignerWithPunctuatedWaterMarks
インターフェイスが含まれます。
抽出タイムスタンプとウォーターマークの生成方法を定義します。2 つのタイプがあります
AssignerWithPeriodicWatermarks
- WaterMark を定期的に生成: システムは定期的に WaterMark をストリームに挿入します。
- デフォルトの期間は200 200です200ミリ秒。 を
ExecutionConfig.setAutoWatermarklnterval()
使用して設定できます。 BoundedOutOfOrderness
定期的なウォーターマークに基づいています。
AssignerWithPunctuatedWatermarks
- タイムサイクルルールはなく、ウォーターマークの生成は中断される可能性があります
定期生成 | 特別な記録から生成 |
---|---|
リアルタイムドライブ | データ駆動型 |
タイムスタンプが割り当てられるたびに、生成メソッドが呼び出されます。 | 時々、generate メソッドを呼び出します。 |
成し遂げるAssignerWithPeriodicWatermarks |
成し遂げるAssignerWithPunctuatedWatermarks |
21. データ遅延が非常に深刻な場合はどうすればよいですか? WaterMarkだけで対応できるのでしょうか?どのように解決すればよいでしょうか?
WaterMark + EventTimeWindowの仕組みを利用することでデータの乱れの問題はある程度解決できますが、WaterMark の水位は万能ではなく、場合によってはデータの遅延が非常に深刻になるため、Watermark + EventTimeWindow を利用しても不可能です。すべてのデータが入力されるのを待ちます。ウィンドウが計算をトリガーした後、ウィンドウに属する遅延データについて、Flink はデフォルトで大幅に遅延したデータを破棄するため、ウィンドウが再度処理されます。
次に、特定の時間範囲内の遅延データが破棄されるのを防ぎたい場合は、Allowed Lateness (遅延を許可するメカニズム/サイドチャネル出力メカニズム) を使用して、許容遅延時間とサイドチャネル出力オブジェクトを設定することで問題を解決できます。 。
WaterMark + EventTimeWindow + 許容遅延ソリューション (サイド チャネル出力を含む)を使用しても、データ損失は発生しません。
API呼び出し
allowedLateness(lateness:Time)
: 遅延の許容時間を設定します。
このメソッドは、Time 値を渡して、データの遅延到着が許可される時間を設定します。これは、WaterMark の時間の概念とは異なります。
要約すると、WaterMark = データのイベント時間 - 順序外の時間値が許可されます。新しいデータが到着すると、WaterMark の値は最新のデータ イベント時間に更新されます。順序が狂った時間値は許可されますが、この時点で履歴データが到着した場合、WaterMark の値は更新されない。
一般に、WaterMark は決して後戻りすることはなく、可能な限り多くの順序外のデータを受信するように設計されています。
ここでの時間の値はどうでしょうか? 主な理由は遅いデータを待つためで、このウィンドウに属するデータが到着しても計算は実行されます(計算方法の詳細は後述します)。
注: このメソッドは、EventTime ベースのウィンドウ専用です。
sideOutputLateData(outputTag:OutputTag[T])
: 遅延データを保存
このメソッドは、遅延データを指定された outputTag パラメーターに保存するもので、OutputTag は遅延データをマークするために使用されるオブジェクトです。
DataStream.getSideOutput(tag:OutputTag[X])
: 遅延データを取得します
window などの操作によって返される DataStream を通じてこのメソッドを呼び出し、遅延データをマークするオブジェクトを渡して遅延データを取得します。