構造

KafkaストリームはKafkaプロデューサとコンシューマ ライブラリ上で構築し、データの並行、分散調整、耐障害性および操作の単純化のためにKafkaの本来の機能を利用して、アプリケーション開発を単純化します。この章ではKafkaストリームが背後でどのように動作するかを説明します。

以下の図はKafkaストリーム ライブラリを使うアプリケーションの内部構造を示します。幾つか詳細を見てみましょう。

ストリームのパーティションとタスク

格納と転送のためのKafkaパーティション データのメッセージ層。処理のためのKafkaストリーム パーティション データ。両方の場合で、このパーティション化はデータのローカリティ、エラスティシティ、スケーラビリティ、高パフォーマンスおよび耐障害性を有効にするものです。KafkaストリームはKafkaトピックに基づいた並行モデルの論理ユニットとしてパーティションタスクの概念を使用します。並行度の意味でKafkaストリームとKafkaストリームの間には密接な関係があります。

  • ストリーム パーティションは全体としてデータレコードの順番に並んだ順列であり、Kafkaのトピック パーティションにマップされます。
  • ストリーム内のデータ レコードはトピックからKafkaのメッセージ にマップされます。
  • データレコードのキーはKafkaとKafkaストリームの両方のデータの分割を決定します。つまり、どのようにデータがトピック内の特定のパーティションに発送されるか。

アプリケーションのプロセッサのトポロジはそれを複数のタスクに入れることでスケールされます。もっと具体的には、Kafkaストリームはアプリケーションのための入力ストリームパーティションに基づいて固定数のタスクを作成します。各タスクは入力ストリーム(つまり Kafkaトピック)からパーティションのリストを割り当てられます。タスクへのパーティションの割り当ては各タスクがアプリケーションの並行度の固定された単位になるように変更されません。タスクは割り当てられたパーティションに基づく独自のプロセッサのトポロジをインスタンス化することができます; それらは割り当てられたパーティションのそれぞれのためにバッファも維持し、それらのレコードバッファから一度に1つのメッセージを処理します。結果としてストリームのタスクは独自に手動の介入無しに並行して処理することができます。

わずかに簡略化して、アプリケーションが実行できる最大並列処理は、アプリケーションが読み取る入力トピックのパーティションの最大数によって決定されるストリームタスクの最大数によって制限されます。例えば、入力トピックに5つのパーティションがある場合、5つまでのアプリケーションのインスタンスを実行することができます。これらのインスタンスはトピックのデータを共同で処理します。入力トピックのパーティションよりも多くのアプリインスタンスを実行すると、“超過した” アプリインスタンスは起動しますが、アイドル状態のままになります; ビジー状態のインスタンスの1つがダウンすると、アイドル状態のインスタンスが前のインスタンスの作業を再開します。

Kafkaストリームがリソースマネージャーではなく、ストリーム処理アプリケーションを実行する場所で "runs" するライブラリであることを理解することが重要です。アプリケーションの複数のインスタンスが同じマシーンあるいは複数のマシーンに渡って広がるかのどちらかで実行されます。タスクはライブラリによって自動的にそれらの実行中のアプリケーションのインスタンスに分散することができます。タスクへのパーティションの割り当ては変更されません; もしアプリケーションのインスタンスが失敗する場合、それに割り当てられたすべてのタスクは自動的に他のインスタンス上で再起動され、同じストリームパーティションから消費を続けるでしょう。

注意: トピックパーティションはタスクに割り当てられ、タスクは全てのインスタンスの全てのスレッドに割り当てられます。これにより、ステートフルタスクの負荷分散とスティッキネスのトレードオフが図られます。この割り当てでは、Kafka ストリームは StreamsPartitionAssignor クラスを使い、別の割り当て者に変更できません。別の割り当て者を使おうとすると、Kafka ストリームはそれを無視します。

以下の図はそれぞれ入力ストリームの1つのパーティションに割り当てられた2つのタスクを示します。


スレッド モデル

Kafkaストリームによりユーザはライブラリがアプリケーション インスタンス内で並行処理をするために使うことができるスレッド の数を設定することができます。各スレッドはそれらのプロセッサのトポロジを使って単独で1つ以上のタスクを実行することができます。例えば、以下の図は2つのストリームタスクを実行する1つのストリームスレッドを示します。

もっと多くのアプリケーションのストリームスレッドあるいはインスタンスを開始することは、ただトポロジをリプリケートし、それがKafkaのパーティションの異なるサブセットを処理し、効果的に処理を並行化することに過ぎません。スレッドの間で共有される状態は無いことに注意することに価値があります。つまり内部スレッドの調整が必要ありません。これはアプリケーションのインスタンスとスレッドに渡って並行してトポロジを実行することをとても簡単にします。様々なストリームスレッドに渡ってKafkaトピックのパーティションの割り当てはKafkaの調整の機能を使うKafkaストリームによって等価的に処理されます。

上で説明したように、Kafkaストリームを使ってストリーム処理アプリケーションをスケールすることは簡単です: アプリケーションの追加のインスタンスを開始するだけで、Kafkaストリームはアプリケーションインスタンス内で実行するタスクに渡ってパーティションの分散の面倒をみます。アプリケーションの全ての実行中のインスタンスに渡って各スレッド(あるいは実行しているタスク)が処理するタスクが少なくとも1つの入力パーティションを持つように、入力Kafkaトピックパーティションと同じ数だけのアプリケーションのスレッドを開始することができます。


ローカル状態ストア

Kafkaストリームはstate storesと呼ばれるものを提供します。これはストリーム処理アプリケーションによってデータを格納およびクエリするために使うことができます。これはステートフルなオペレーションを実装する時に重要な機能です。例えば、join() あるいは aggregate()のようなステートフルなオペレーションを呼んでいる時やストリームをウィンドウする時に、KafkaストリームDSLは自動的にそのような状態ストアを生成および管理します。

Kafkaストリームでの各ストリーム タスクは、処理のために必要とされるデータを格納およびクエリするためにAPIを使ってアクセスすることができる1つ以上のローカル状態ストアを埋め込むかもしれません。Kafkaストリームはそのようなローカル状態ストアのための耐障害性および自動的な回復を提供します。

以下の図は専用のローカル状態ストアを持つ2つのストリームタスクを示します。


耐障害性

Kafkaストリームは本質的にKafkaの中で統合される耐障害性の機能に基づいています。Kafkaのパーティションはとても利用しやすくリプリケートされます; つまりストリームデータがKafkaに残る場合、たとえアプリケーションが失敗し再処理しなければならない場合でも利用可能です。Kafkaストリーム内のタスクは障害を処理するためにKafkaコンシューマクライアントによって提供される耐障害性の機能を利用します。もしタスクが失敗したマシーン上で実行する場合、Kafkaストリームは自動的にアプリケーションのインスタンスを実行中の残りのうちの1つの中でタスクを再起動します。

さらに、Kafkaストリームはローカル状態ストアが障害に対して堅牢であるようにもします。各状態ストアに対して、状態の更新を追跡するリプリケートされた変更ログのKafkaトピックを保持します。これらの変更ログトピックは各ローカル状態ストアのインスタンス、従ってストアへアクセスするタスクが独自の専用の変更ログトピックパーティションを持つようにパーティション化もされます。ログのコンパクションはトピックが無限に成長しないように古いデータを安全に消去できるように変更ログのトピック上で有効にされます。他のマシーン上で失敗し再起動されたタスクがあるマシーン上で実行される場合、Kafkaストリームは新しく開始されたタスクの処理を再開する前に、関連する変更履歴トピックを再生することで、失敗前の関連する状態ストアをコンテントに復元することを保証します。結果として障害の処理はエンドユーザに対して完全に透過です。

タスクの(再)初期化のコストは一般的に変更ログのトピックに関係する状態ストアの再生による状態の回復のための時間に主に依存することに注意してください。この回復時間を最小化するために、ユーザはローカル状態(つまり状態の完全にリプリケートされたコピー)の待機レプリカを持つ様にアプリケーションを設定することができます。When a task migration happens, Kafka Streams will assign a task to an application instance where such a standby replica already exists in order to minimize the task (re)initialization cost. Kafka ストリームの設定の章のnum.standby.replicas を見てください。Starting in 2.6, Kafka Streams will guarantee that a task is only ever assigned to an instance with a fully caught-up local copy of the state, if such an instance exists. Standby tasks will increase the likelihood that a caught-up instance exists in the case of a failure.

inserted by FC2 system