重要: Scalaに依存するMaven アーティファクトはScalaのメジャーバージョンが後ろに付きます。例えば、"2.10" あるいは "2.11"。プロジェクトwiki上のマイグレーションガイドに相談してください。

概念

プログラムとデータフロー

Flinkプログラムのブロックを構築する基本はストリーム変形です (データセットも内部的にはストリームであることに注意してください)。stream は中間結果で、transformation は入力として1つ以上のストリームを取る操作で、それらから1つ以上の結果のストリームを計算します。

実行された場合、Flinkプログラムはストリームと変形オペレータから成るストリーミング データフローにマップされます。各データフローは1つ以上のソース で始まり、1つ以上のシンクに終着します。データフローは任意の有効非循環グラフ (DAGs)に似ているかも知れません。(iterationの概念によって特別な形式の循環が許されますが、簡単化のためにここでは省略します)。

ほとんどの場合、プログラム内の変換とデータフロー内のオペレータの間には1対1の対応があります。しかし、時には1つの変換が複数の変換オペレータからできているかも知れません。

データストリームプログラムとそのデータフロー。

上に戻る

並行データフロー

Flinkでのプログラムは本質的に並行および分散です。ストリームストリームパーティション に分割され、オペレータオペレータ サブタスクに分割されます。オペレータ サブタスクは異なるスレッド内で異なるマシーンあるいはコンテナ内でお互いに独立して実行されます。

オペレータサブタスクの数は特定のオペレータの並行度 です。ストリームの並行度は常にその生成オペレータの並行度です。プログラムの異なるオペレータは異なる並行度を持つかも知れません。

並行データフロー

ストリームはone-to-one (あるいは forwarding) パターン、あるいは redistributing パターンの中での二つのオペレータ間でデータを転送することができます。

  • One-to-one ストリーム(例えば、sourcemap() オペレータ間)はパーティショニングと要素の順番を維持します。source オペレータのサブタスク[1]によって生成されたので、map()オペレータのサブタスク[1]が同じ順番で同じ要素を見るだろうことを意味します。

  • Redistributing ストリーム (map()keyBy/window間、およびkeyBy/windowsink間) はストリームのパーティショニングを変更します。各 オペレータのサブタスクは、選択された変換に依存して、データを異なるターゲットのサブタスクに送信します。Examples are keyBy() (re-partitions by hash code), broadcast(), or rebalance() (random redistribution). redistributing 交換の場合、送信および受信タスクのそれぞれのペアについての要素間の順番のみが維持されます(たとえば、map()のサブタスク[1]とkeyBy/windowのサブタスク[2])。

上に戻る

タスク & オペレータのチェイン

分散実行について、Flinkはオペレータのサブタスクをタスク繋ぎ込みます。各タスクは1つのスレッドによって実行されます。オペレータをタスクに繋ぎ込むことは、最適化に便利です: スレッドからスレッドへの移譲とバッファリングを減らし、レイテンシを減らす一方で全体のスループットを増加させます。繋ぎ込みの挙動はAPIで設定することができます。

以下の図のデータフローの例は5つのサブタスク、したがって5つの平行スレッドで実行されます。

オペレータのタスクへの繋ぎ込み

上に戻る

分散実行

Master, Worker, Client

Flinkのランタイムは二つの種類の処理から成ります。

  • マスター プロセス(JobManagersとも呼ばれます) は分散実行を調整します。それらはタスクのスケジュール、チェックポイントの調整、障害時の再開の調整などを行います。

    常に少なくとも一つのマスタープロセスがあります。高可用性セットアップは複数のマスタープロセスを持つでしょう。そのうちの一つはleaderで、その他はstandbyです。

  • worker (TaskManagersとも呼ばれます) はデータフローのtasks (あるいはもっと明確にはサブタスク)を実行し、バッファしてデータstreamsを交換します。

    常に少なくとも一つのワーカープロセスがあります。

マスターとワーカーは任意のやり方で開始することができます: 直接マシーン上で、コンテナを使って、あるいはYARNのようなリソースフレームワークを使って。ワーカーはマスターに接続し、それら自身を利用可能だと宣言し、作業を割り当てられます。

client はランタイムおよびプログラムの実行の一部ではありませんが、データフローを準備しmasterに送信します。そのあとで、クライアントは切断、あるいは進捗レポートを受信するために接続したままでいることができます。クライアントは実行を開始するJava/Scalaのどちらの一部として実行するか、コマンドライン処理 ./bin/flink run ...の中で実行します。

実行中のFlinkデータフローに含まれた処理

上に戻る

ワーカー、スロット、リソース

各ワーカー (TaskManager) はJVM プロセスで、個々のスレッドで1つ以上のサブタスクを実行するかもしれません。どれだけの数のタスクをワーカープロセスが受け付けるかを制御するために、ワーカーはタスク スロット (少なくとも1つ)と呼ばれるものを持ちます。

タスク スロット はタスクマネージャーのリソースの固定のサブセットを表します。3つのスロットを持つTaskManagerは、管理しているメモリの1/3を各スロットに捧げるでしょう。Slotting the resources means that a subtask will not compete with subtasks from other jobs for managed memory, but instead has a certain amount of reserved managed memory. CPUの分離はここで起こらず、スロットは現在のところタスクの管理しているメモリを分割するだけであることに注意してください。

タスクスロットの数を調整することで、ユーザはサブタスクがお互いに隔離される方法を定義することができます。タスクマネージャーごとに1つのスロットを持つことは、各タスクグループが別個のJM内で実行することを意味します。(例えば、別個のコンテナ内で開始することができます)。複数のスロットを持つことは、多くのサブタスクが同じJVMを共有することを意味します。同じJVM内のタスクは(マルチプレクサを使って)TCP接続とハートビートメッセージを共有することを意味します。それらはデータセットとデータ構造も共有するかもしれません。したがってタスクあたりのオーバーヘッドを減らします。

タスクスロットを持つタスクマネージャーとタスク

デフォルトで、サブタスクが異なるタスクの部分集合だが同じジョブからのものである場合、Flinkを使ってサブタスクがスロットを共有することができます。The result is that one slot may hold an entire pipeline of the job. このスロットの共有 を認めることには、二つの主要な利益があります:

  • ジョブ内で使われる最も高い並行度として、Flinkクラスタはタスクスロットと完全に同じ数を必要とします。No need to calculate how many tasks (with varying parallelism) a program contains in total.

  • より良いリソースの利用をすることが容易です。Without slot sharing, the non-intensive source/map() subtasks would block as many resources as the resource intensive window subtasks. With slot sharing, increasing the base parallelism from two to six yields full utilization of the slotted resources, while still making sure that each TaskManager gets only a fair share of the heavy subtasks.

スロットの共有の挙動は、望ましく無い場所での共有を避けるために、API内で制御することができます。そのための仕組みがリソースグループです。それらは何の(サブ)タスクがスロットを共有するかを定義します。

経験則で、タスクスロットの良いデフォルト値はCPUのコア数です。ハイパースレッディングを使って、各スロットは2つ以上のハードウェア スレッド コンテキストを取ります。

共有されたタスクスロットを持つタスクマネージャ

上に戻る

時間とウィンドウ

集約イベント(例えば、カウント、合計)は、バッチ処理に比べてストリーム上では少し異なる働きをします。例えば、ストリームは一般的に無限なため、最初にストリーム内で全ての要素を数えることは不可能で、したがってカウントを返します。代わりに、ストリーム上の集約(カウント、合計など)は“count over the last 5 minutes” あるいは“sum of the last 100 elements”のようなwindowsによってスコープされます。

ウィンドウはtime driven (例: 各30秒毎) あるいは data driven (例: 各100要素毎)があり得ます。One typically distinguishes different types of windows, such as tumbling windows (no overlap), sliding windows (with overlap), and session windows (gap of activity).

時間とカウント ウィンドウ

このブログの投稿の中でもっと多くのウィンドウの例を見つけることができます。

上に戻る

時間

ストリーミングプログラムの中で(例えばウィンドウを定義するために)時間を参照する場合、時間の異なる表記を指示することができます。

  • イベントタイム は、イベントが生成された時間です。通常はイベントのタイムスタンプによって表現されます。例えば、センサーの生成あるいは生成サービスによってアタッチされたもの。Flinkはtimestamp assignersを使ってイベントのタイムスタンプにアクセスします。

  • Ingestion time はイベントがソースオペレータにおいてFlinkデータフローに入った時間です。

  • Processing Time は時間ベースのオペレーションを実施する各オペレータでのローカルの時間です。

イベントタイム、取り込み時間、処理時間

時間を扱う方法についての詳細はイベントタイム ドキュメントにあります。

上に戻る

状態と耐障害性

データフロー内の多くのオペレーションは単純に1つの個々のそのときのイベントを見ますが(例えば、イベントパーサー)、いくつかのオペレーションは個々のイベントを横断して情報を記録します(例えば、ウィンドウ オペレーション)。これらのオペレーションはステートフルと呼ばれます。

ステートフルのオペレーションは組み込みのキー/値ストアとみなすことができるものの中で維持されます。状態はステートフル オペレータによって読み込まれたストリームと一緒に厳密にパーティション化され分散されます。したがって、キー/値 状態へのアクセスはkeyBy() 関数の後のkeyed streams上でのみ可能で、現在のイベントキーの値によみ限定されます。ストリームと状態のキーの割り当ては、トランザクションのオーバーヘッド無しにすべての状態の更新がローカルオペレーションであることを確実にします。この割り当てはFlinkが状態を再分配しストリームのパーティショニングを透過的に調整することも可能にします。

状態とパーティショニング

上に戻る

耐障害性のためのチェックポイント

Flinkはストリーム再生チェックポイントを使って耐障害性を実装します。チェックポイントはストリーム内の一貫性のあるポイントとストリーミングデータフローが再開できる状態を定義し、一貫性を維持します (確実に一回の処理セマンティクス)。入力ストリームから再生される最後のチェックポイントから、イベントと状態が更新されます。

The checkpoint interval is a means of trading off the overhead of fault tolerance during execution, with the recovery time (the amount of events that need to be replayed).

チェックポイント耐障害性の詳細は耐障害性のドキュメントにあります。

チェックポイントとスナップショット

上に戻る

バックエンドの状態

キー/値 インデックスが格納されている正確なデータ構造は、選択された状態のバックエンドに依存します。ある状態バックエンドはインメモリのハッシュマップ内にデータを格納し、またある状態バックエンドはキー/値インデックスとしてRocksDBを使います。状態を保持するデータ構造の定義に加えて、状態バックエンドはキー/値 状態のある時点のスナップショットを取り、スナップショットをチェックポイントの一部として格納するロジックも実装します。

上に戻る

ストリーミングのバッチ

Flink はバッチプログラムをストリーミングプログラムの特別な場合として実行します。この時ストリームは制限(要素の数が有限)されます。DataSet は内部的にデータのストリームとして扱われます。上記の概念はしたがって少しの例外を除いてストリーミングプログラムに適用される方法と同じようにバッチプログラムに適用されます:

  • データセットAPI中のプログラムはチェックポイントを使いません。回復は完全にストリームを再現することで起こります。入力が制限されているため、それらが可能です。このことは回復のためのコストを押し上げますが、チェックポイントを回避するため一般的な処理を手軽にします。

  • データセットAPI内のステートフル オペレーションは、キー/値 インデックスでは無く、単純化されたインメモリ/アウトオブコアのデータ構造を使用します。

  • データセットAPIは特別な同期(スーパーステップ ベース)のイテレーションを導入します。これは制限されたストリーム上でのみ可能です。詳細はイテレーションのドキュメントを調べてください。

上に戻る

TOP
inserted by FC2 system