Kekeの日記

エンジニア、読書なんでも

Apache FlinkのExactly-onceを探ってみる

image.png

1. Apache Flinkとは

Apache Flinkとは、データストリーム上でのステートフルな処理システムである

注意:本記事で使う画像は参考文献から引用させていただきます

1.1 特徴

  • ストリーム処理をするようなあらゆるユースケースでフィットすることができる
    • イベント駆動アプリケーション
    • ストリーム、バッジ処理
    • データパイプライン、ETL
  • メッセージストリームセメンティクスExactly-onceのサポート
    • Exactly-onceステート一貫性
    • イベント時間処理
    • 遅延データハンドリング
  • バッジ処理、ストリーム処理など階層的なAPIを提供
    • SQL言語をストリーム、バッジデータに使うことができる
    • データストリーム処理APIとデータセットAPI
    • プロセス処理関数
  • オペレーションに特化している
    • 柔軟なデプロイ
    • 高い設定性
    • セーブポイント
  • スケーラビリティ
    • スケールアウトできるアーキテクチャ
    • 非常に大きなステートのサポート
    • インクリメンタルなチェックポイント
  • パフォーマンスが素晴らしい
    • 低レイテンシ
    • 高スループット
    • インメモリコンピューティング

2. ユースケース

Apache Flinkはあらゆるユースケースにフィットして採用することができます。

Flinkはストリーム、バッジ処理やステート管理、イベント時間セマンティクスをサポートして、何よりExactly-onceセマンティクスをサポートしています。

また、KubernetesやApache Mesosなどあらゆるリソースに対応しています。

2.1 イベント駆動アプリケーション

2.1.1 概要

ステートの変更や外部アクションをトリガーして、一つ以上のストリームからデータを取得して、ステートと入力のデータと作用している。

今までのレストフルな通信(httpなど)に比べるとデータベースが外部にあったりしたのとは異なる。

イベント駆動アプリケーションはステートフルなストリーム処理アプリケーションに基づく。 何よりデータそのものと、処理が同一のロケーションにあるアプリケーションである。

以下の図に示す。

image.png

2.1.2 メリット

このアーキテクチャのメリットは何でしょうか?

データと処理が物理的な距離がないので、低レイテンシと高スループットを実現している。 定期的な、またはインクリメンタルなチェックポイントが永続ストレージと同期することができる。

また、いろんなアプリケーションから参照されるようなデータベースだと、何かしら整合性を気にしなければならない。

しかし、Flinkでは、それぞれのイベント駆動アプリケーションがそれぞれのデータに対してしか責任を持たないので、低い整合性ですみ、スケールしやすい。

2.1.3 どのように動作するのか

Exactly-once保証で数テラバイトまで管理できるステートを持っている。

しかしながら、もっとも特出しているのはセーブポイントであろう。 セーブポイントは、一貫性を持ったステートのイメージであり、アプリケーションはスケールを変更やA/Bテストなどのマルチバージョンでも使うことができる。

2.2 データ分析アプリケーション

2.2.1 概要

解析の仕事は生データから情報を抽出して、ビジネスに活かしたりする。

従来はバッジ処理を基本とする。

しかし、洗練されたストリーム処理エンジンでは、リアルタイムでデータを見ることができます。

解析した結果は、データベースやアプリのステートに保存することができる。

image.png

2.2.2 メリット

以下のデータパイプラインとほぼ同様なので、ここでは解説をしない。

2.3 データパイプラインアプリケーション

2.3.1 概要

データパイプラインは、ETLなどデータを転送したり、データマートに入れたりする目的で使われる。

データを変換して、データをリッチにして、他のデータストアに保存しなおすといったような流れである。

ストリーム処理があればバッジ処理を繰り返したりする必要がなく、リアルタイムにデータを見ることができるため非常にデータが活きてくるわけである。

image.png

2.3.2 メリット

一般的にバッジ処理だと断続的なデータ解析になってしまうが、データパイプラインを構築することで継続的にデータを処理して、データを出力することができる。

3. アーキテクチャ、コンセプト

データフローを構築する中で、以下のような概念が重要となる。

3.1 抽象化のレベル

抽象化のレベルは非常に簡潔にまとめられている。

image.png

もっとも低いレイヤーがストレートフルストリームである。 ユーザーが一つ以上のストリームからイベントを処理して、一貫性のある耐障害性を使える。また、イベント時間とコールバック関数をも定義することができる。

次にCoreなAPIへあるDataStreamAPIDataSetAPIがあり、ほとんどのApache Flinkで開発するようなアプリケーションはこれを使うことになる。

これらのAPIはデータ処理のためのブロックを作ったり、集約、変換、結合などの処理を行えます。

次にTableAPIです。 テーブルAPIは、テーブルに関することです。スキーマをもってupdate, joinや集約をできるようになっています。

もっとも高いレベルがSQLとなっています。 非常にTableAPIと似ているのですが、SQL表現であることから違う。

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

Flinkでのデータフローの単位はストリームと変換である。

ストリームとは、概念的には、理想的に無限に続くデータのレコードであり、変換とは、データを入力として受けて、処理の結果としてデータを出力するものである。

実行されるとストリームと、変換を含むFlinkのコードはストリーミングデータフローにマッピングされる。

そして、データフローはソースから始まって、シンクで終わる。

また、任意のDAGで表される。

image.png

3.3 並列的なデータフロー

Flinktのプログラムはもともと分散していて、並列である。実行の間は、ストリームはストリームパーティションと呼ばれ、変換処理などをするオペレーターはオペレーターサブタスクと呼ばれるものを持つ。それぞれは別のスレッドで走り、独立である。

並行度は、オペレーションタスクの数で決まる。

image.png

ストリームはオペレーター間を二つのパターンで配送することができる。

  1. One-to-one ストリーム: 一対一の関係である。順序保証がある。
  2. Redistributing ストリーム: 多くのオペレーターに出力するようなもの。順番保証性はない。

3.4 ウィンドウ

イベントを集約するのはバッジ処理と大きく異なります。

しかしながら、文字数カウンタなど、無限に逐一処理するなど、明らかに難しいものはあります。

なので、ウィンドウという定期的に処理をする関数を定義して使います。

image.png

3.5 タイム

Apache Flinkならず、他のストリーム処理でも時間の概念を抑えることは重要です。

  • イベント時間: イベントが作成された時間
  • 取得時間: 外部ソースからイベントを取得した時の時間
  • プロセス時間: プロセスの時間

image.png

3.6 ステートフルなオペレーション

データフローの中で、オペレータがイベントを見るなかで、いくつかのイベントはイベントを保持しているステートフルな状態である。

key/valueで保存されていて、指定したkeyのオペレーターに繋ぐことができる。

image.png

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

耐障害性のために、stream replycheckpointingを使っている。

チェックポイントは、入力ストリームのそれぞれの特定の場所に基づく。 ストリームのデータフローはチェックポイントを参照することでExactly-onceをサポートできている。データに欠損を作ってしまうと、状態を戻して、再度チェックポイントからイベントを再処理する。

チェックポイントの間隔は、オーバーヘッドと耐障害性とのトレードオフである。     

3.8 ストリームにバッジ処理をする

大規模なバッジ処理をすることができる。

4. 分散ランタイム環境

4.1 タスクとオペレーターチェーン

分散処理をする中で、Flinkはサブタスクオペレーターをタスクにチェーンする。

それぞれのタスクはApache Stormなどと同様に一つのプロセスである。

チェーンによってタスク間でのオーバーヘッドを減少させ、パフォーマンスを改善している。

image.png

4.2 ジョブマネージャー、タスクマネージャー、クライアント

先ほどのプロセスとあっても、二種類のプロセスがある。

  • ジョブマネージャー: 分散処理をまとめる。マスターと呼ばれる。
  • タスクマネージャー: データフローのタスクを実行する。

また、クライアントはプログラムの実行には関わってはいませんが、ジョブフローを準備して、送信するのに使う。進捗なども受け取ることができる。

image.png

4.3 タスクスロットとリソース

それぞれのタスクマネージャー(ワーカー)は、スレッドを実行するが、どのくらいそのワーカーがタスクを実行できるかを制御するための仕組みがタスクスロットである。

以下の図のような構成になっている。

image.png

4.4 ステートバックエンド

ステートを管理するための実際のデータ構造はステートバックエンドに依存する。

あるバックエンドはインメモリハッシュマップを使用して、あるものはRockDBを使用したりしてkey/valueデータを保存している。

それに加えて、ステートバックエンドはkey/valueの状態のスナップショットをとってチェックポイントに格納している。

image.png

4.5 セーブポイント

Data Stream APIを使って書かれたプログラムなら、実行をセーブポイントから回復することができます。

セーブポイントは手動でトリガーされるチェックポイントのことであり、スナップショットをステートバックエンドから取得する。このシステムはチェックポイントの機構に依存している。

セーブポイントはコマンドラインか、RESTAPIから作成することができる。

5. まとめ

  • Apache Flinkはかなり万能である印象を受けた
  • Exactly-onceをチェックポイントで実現している
  • ストリーム処理の概念自体はあまり他のものと大差があるわけではない

次はMacにスタンドアローン環境でセットアップしてみたいと思います。

参考文献