Apache Kafka - ストリーム処理


ここに画像の説明を挿入


概要

Kafka は、イベント ストリームを確実に配信できる強力なメッセージ バスとして広く認識されており、ストリーム処理システムにとって理想的なデータ ソースです。ストリーム処理システムは通常、リアルタイム データ ストリームを処理するコンピューティング システムを指します。これは、データをリアルタイムで処理および分析し、必要に応じて対応する応答と操作を実行できます従来のバッチ処理システムとは異なり、ストリーミング システムはデータが到着するとすぐに処理できるため、リアルタイムの監視とアラート、リアルタイムの推奨事項、リアルタイムの応答など、リアルタイムの応答を必要とするアプリケーションに特に適しています。広告配信など。

Kafka の設計により、高スループット、低遅延、信頼性、および大量のデータを処理するために簡単に拡張できる機能により、Kafka はストリーム処理システムにとって理想的なデータ ソースになります。Apache Storm、Apache Spark Streaming、Apache Flink、Apache Samza などの多くの Kafka ベースのストリーム処理システムは、さまざまなシナリオに適用されて成功しています。

Kafka のストリーム処理クラス ライブラリは、リアルタイム データ ストリームを処理するためのシンプルかつ強力な方法を提供し、Kafka クライアント ライブラリの一部として提供されます。これにより、開発者は外部処理フレームワークに依存せずに、アプリケーション内で直接イベントを読み取り、処理し、生成することができます。Kafka のストリーム処理クラス ライブラリは、ウィンドウ処理、状態ストレージ、ストリーム処理トポロジ構築などの多くの便利な機能を提供し、開発者が強力なストリーム処理アプリケーションを簡単に構築できるようにします。

Kafka の人気とストリーム処理テクノロジの発展により、ストリーム処理システムはデータ処理の重要な分野となり、ますます多くのアプリケーション シナリオで広く使用されるようになりました。Kafka のストリーム処理クラス ライブラリは、リアルタイム データ ストリームを処理し、そこから有用な情報を抽出するための強力なツールを開発者に提供し、複雑なストリーム処理システムを構築するのに理想的な選択肢です。


ストリーミングとは

ストリーミングは、1 つ以上のイベント ストリームをリアルタイムで処理するためのプログラミング パラダイムです。イベント ストリームは、無限で継続的に増加し、時間の経過とともに新しいレコードが追加される無制限のデータセットの抽象表現です。

バッチ処理とは異なり、ストリーミングでは、すべてのデータが利用可能になるのを待つことなく、イベント ストリームをリアルタイムで処理できます。このため、ストリーミングは、不審な取引アラート、ネットワーク アラート、リアルタイムの価格調整、荷物追跡など、リアルタイムの応答が必要なビジネス シナリオに最適です。

ストリーム処理には次の特徴があります。

  • Ordered : イベント ストリーム内のデータ レコードは、発生した順序で並べられます。これは、ストリーミングがイベントを発生順に処理できるため、正しい結果が得られることを意味します。

  • Immutable : イベント ストリーム内のデータ レコードは不変です。つまり、レコードが作成されると変更できません。これにより、同時変更の問題を気にする必要がなくなるため、ストリーミングの実装が容易になります。

  • Replayable : イベント ストリーム内のデータ レコードは繰り返し処理できるため、ストリーミングの耐障害性が高まります。処理中にエラーが発生した場合は、正しい結果が得られるまで同じデータ レコードを再処理できます。

  • 低遅延: ストリーミングの遅延は短く、イベントのストリームを処理する時間が短く、通常はミリ秒またはマイクロ秒のオーダーです。このため、ストリーミングはリアルタイムの応答が必要なビジネス シナリオに非常に適しています。

  • 高スループット: ストリーム処理のスループットは高く、大量のデータ レコードを処理できます。このため、ストリーミングは大規模なデータセットの処理に最適です。

  • 特定のフレームワークや API に依存しない: ストリームの定義は特定のフレームワーク、API、または機能に依存せず、無制限のデータ セットからデータを読み取って処理する限り、ストリーム処理を実行できます。これにより、ストリーミングの柔軟性と拡張性が向上します。

ストリーム処理は、無制限のデータ セットをリアルタイムで処理できるプログラミング パラダイムです。順序、不変性、再生可能性、低遅延、高スループット、および柔軟性の特性を備えており、リアルタイム応答を必要とするビジネス シナリオに非常に適しています。


ストリーム処理のいくつかの概念

時間

時間はおそらくストリーミングにおいて最も重要な概念であり、最もわかりにくい概念です。分散システムについて議論する際に、時間の複雑な概念をどのように理解すればよいでしょうか? ストリーム処理では、ほとんどのストリーム アプリケーション操作が時間ウィンドウに基づいているため、時間は非常に重要な概念です。もの

  • イベント時間: イベントが実際に発生した時間。これは時間の最も重要な概念であり、ほとんどのストリーミング アプリケーションはイベント時間に基づいてウィンドウ操作と集計を実行します。
  • ログ追加時刻 (Log Append Time): イベントが Kafka に書き込まれる時刻。この時間は主に Kafka の内部で使用され、ストリーミング アプリケーションとはほとんど関係ありません。
  • 処理時間: アプリケーションがイベントを受信して​​処理を開始する時間。この時間は信頼性が低く、異なる値が生成される可能性があるため、ストリーミング アプリケーションで使用されることはほとんどありません。

これらの時間の概念、特に分散システムのコンテキストにおける複雑さをより深く理解するために、Justin Sheehy の論文「There is No Now」を読むことをお勧めします。

ストリーミング システムでは、プロデューサーにネットワークの問題が発生し、数時間オフラインになった後、大量のデータが流入すると、システムに大きな問題が発生します。ほとんどのデータのイベント時間が設定したウィンドウ範囲を超えているため、通常の集計計算を実行できません。

この問題を解決するために、ストリーミング システムはいくつかのメカニズムを提供します。

  1. データをウィンドウ外にドロップする: 単純ですがデータ損失につながります
  2. ウィンドウを調整します。ウィンドウを拡張してより多くのデータを含めますが、ウィンドウ範囲が大きくなると計算精度に影響します。
  3. データの再送信: プロデューサーはオフライン期間中にデータを再送信し、システムは正しい結果を生成するために補足計算を実行します。
  4. ウォーターマーク: データが遅れる最大時間を指定することができ、システムはウォーターマーク時間内のデータが到着するのを待ってから計算を開始し、結果を出力します。ウォーターマーク メカニズムは、結果の正確性を確保しながら、データ到着の遅れの問題を効果的に解決できます。

したがって、ストリーミング アプリケーション、特に遅れて到着するデータやオフライン データを設計する際には、これらの時間の概念を考慮し、システムの精度を確保するためにこれに対処する適切なメカニズムを選択する必要があります。


  1. 単一のイベントを処理するのは簡単ですが、複数のイベントが関係する場合は、「状態」と呼ばれるより多くの情報を追跡する必要があります。
  2. 状態は通常、ハッシュ テーブルなどのアプリケーション ローカル変数に保存されます。ただし、ローカル状態が失われるリスクがあり、再起動後に状態が変化するため、最新の状態を永続化して復元する必要があります。
  3. ローカル状態または内部状態: 単一のアプリケーション インスタンスによってのみアクセスでき、組み込みデータベースを使用して維持されます。高速ですが、メモリ サイズによって制限されます。多くの設計では、データをローカル状態処理を使用するサブストリームに分割します。
  4. 外部状態: NoSQL システム Cassandra などの外部データ ストアを使用して維持されます。サイズに制限はなく、複数のアプリケーション インスタンスからアクセスできますが、遅延と複雑さが追加されます。ほとんどのストリーム処理アプリケーションは、外部ストレージを回避するか、ローカルにキャッシュしてインタラクションを減らして遅延を減らし、内部および外部の状態の一貫性の問題を引き起こします。

ストリームとテーブルの二重性

  1. テーブルはレコードのコレクションであり、主キーとスキーマによって属性が定義されています。レコードは変数であり、クエリを実行して特定の時点のステータスを取得できます。たとえば、CUSTOMERS_CONTACTS テーブルはすべての顧客連絡先情報を取得します。ただし、テーブルには履歴情報がありません。
  2. ストリームは一連のイベントであり、各イベントは変化です。表は、マルチミューテーション結果の現在の状態ですテーブルとストリームは同じコインの表裏の関係にあります。変化する出来事や現在の状態に焦点を当てて、世界が変化します。両方のアプローチをサポートするシステムはより堅牢です。
  3. テーブルをストリームに変換するには、Kafka ストリーム処理に変更を送信する CDC ソリューションなど、テーブル変更イベント (挿入、更新、削除) をキャプチャする必要があります。
  4. ストリームをテーブルに変換するには、すべての変更をストリームに適用して状態を変更し、メモリ、内部状態ストレージ、または外部データベースにテーブルを作成し、ストリームのすべてのイベントを走査して状態を 1 つずつ変更し、ある時点の状態テーブル。

靴屋があると仮定すると、小売活動はイベント フローで表すことができます。

「赤、青、緑の靴が到着しました」
「青い靴が売れました」
「赤い靴が売れました」
「青い靴が返品されました」
「緑の靴が売れました」
現在、またはこれまでに倉庫にどのような在庫があるかを知りたい場合これまでに作成したビューを具体化する必要があります。

売上高表のニーズ

ストリーム内のすべての変更イベントを適用して状態を変更し、テーブルを構築します。テーブルからフローへはテーブル上の変更イベントをキャプチャし、後続のストリーム処理のためにストリームに送信する必要があります。表はある瞬間の状態を表し、流れは変化を表し、両者は相互に変容していくものであり、両者をサポートするシステムはより強力なものとなる。


タイムウィンドウ

ストリームのタイム ウィンドウ操作には主に次の種類があります。

  1. ウィンドウ サイズ: 5 分、15 分、1 日など。サイズは変化の検出速度と滑らかさに影響します。ウィンドウが小さいほど、変化の検出は速くなりますが、ノイズが多くなります。ウィンドウが大きいほど、変化は滑らかになりますが、遅延が大きくなります。
  2. ウィンドウが移動する頻度 (「移動間隔」): 5 分間の平均は、1 分ごと、1 秒ごと、または新しいイベントごとに変化します。ウィンドウサイズ分の移動間隔を「ローリングウィンドウ」、レコードごとに移動することを「スライディングウィンドウ」と呼びます。
  3. ウィンドウ更新可能時間: 1 時間後の 00:00 ~ 00:05、00:02 イベントの平均値を計算し、00:00 ~ 00:05 のウィンドウ結果を更新するかどうか? 期間内のイベントを定義できます。対応する時間セグメント (4 時間更新など) を追加します。それ以外の場合は無視されます。
  4. ウィンドウは時間に合わせているかどうか: 5 分のウィンドウは 1 分ごとに移動し、最初のスライスは 00:00 ~ 00:05、2 番目のスライスは 00:01 ~ 00:06、またはアプリケーションはいつでも開始されます (最初のスライス) 03:17~03:22。スライディング ウィンドウは新しいレコードとともに移動しますが、時間と一致することはありません。

ウィンドウ サイズは操作結果の感度と滑らかさに影響し、移動間隔は結果の更新頻度を決定し、更新可能時間は遅いイベントが操作に参加するかどうかを決定します。Windows は時間調整することも、しないこともできます。

スライディング ウィンドウは新しいイベントごとに移動し、ローリング ウィンドウは所定の間隔で移動しますが、どちらもウィンドウ サイズを超えて移動することはありません。ローリングウィンドウの移動間隔がウィンドウサイズと等しい場合、隣接するウィンドウは重なりませんが、スライディングウィンドウの移動間隔がウィンドウサイズより小さい場合、隣接するウィンドウは重なり合います。

ここに画像の説明を挿入
【スクロールウィンドウとジャンプウィンドウの違い】


ストリーミング用のデザインパターン

単一イベントの処理

単一イベントの処理は、ストリーミングの最も基本的なパターンです。このモードは、無駄なイベントをフィルタリングしたり、イベントを変換したりするためによく使用されるため、マップ モードまたはフィルター モードとも呼ばれます。

マップという用語は、マップ フェーズでイベントを変換し、リデュース フェーズで変換されたイベントを集約する Map-Reduce パターンに由来します。

ストリーム イベントを読み取り、変更し、他のストリームに書き込みます。たとえば、ログ ストリームを読み取り、エラー レベルのメッセージを優先度の高いストリームに書き込み、その他の優先度の低いストリームを書き込み、または JSON を Avro 形式に変換します。状態を維持する必要がなく、エラーや負荷分散からの回復が簡単です。

[単一イベント処理トポロジ]
ここに画像の説明を挿入
このパターンは、1 つのプロデューサーと 1 つのコンシューマーを使用して実装できます。


ローカル状態を使用する

ほとんどのストリーム処理アプリケーションは、毎日の株価の高値と安値、移動平均などの情報を集約します。最小値と最大値を保存し、新しい値と比較するなど、ストリームの状態を維持する必要があります。これはローカル状態によって実現でき、以下の図に示すように、各操作は集合体のグループになります。Kafka パーティションでは、同じコード イベントに対して同じパーティションが確保されます。各アプリケーション インスタンスは割り当てパーティション イベントを取得し、一連の銘柄記号の状態​​を維持します。
ここに画像の説明を挿入


多段階の処理と再分割

ローカル状態はグループ内の集計に適しています。1 日あたりの上位 10 株などの完全な情報結果を取得するには 2 つの段階が必要です。最初の段階では、各インスタンスが各株の上昇と下降を計算し、新しい値を書き込みます。単一パーティションのトピック。第 2 段階では、単一のアプリケーション インスタンスが新しいトピックを読み取り、上位 10 の共有を見つけます。新しいテーマには株式の概要のみがあり、トラフィックは少なく、単一のインスタンスで十分です。追加のステップは、複数の Reduce ステップを含む MapReduce に似ており、各ステップは個別に適用されます。ストリーム処理フレームワークは複数のステップで適用でき、フレームワークはステップごとにどのアプリケーション インスタンスを実行するかをスケジュールします。

ここに画像の説明を挿入

[ローカル状態と再分割手順を含むトポロジ]


外部ルックアップの使用 - ストリームとテーブルの結合

ここに画像の説明を挿入
【外部データソースを利用したスト​​リーム処理】

外部検索により大幅な遅延が発生する

より優れたパフォーマンスと強力なスケーラビリティを実現するには、ストリーミング アプリケーションでデータベースの情報をキャッシュする必要があります。ただし、このキャッシュの管理も課題です。

たとえば、キャッシュ内のデータが最新であることを確認するにはどうすればよいでしょうか? 頻繁に更新しすぎると、データベースに負荷がかかり、キャッシュが役に立たなくなります。更新が適時に行われないと、ストリーミングで使用されるデータが古くなってしまいます。

データベース変更イベントをキャプチャしてイベント ストリームを形成できる場合、ストリーム処理ジョブはイベント ストリームを監視し、適時にキャッシュを更新できます。データベース変更イベントをキャプチャしてイベント ストリームを形成するプロセスは、CDC (Change Data Capture) と呼ばれます。Connect を使用すると、CDC タスクを実行してデータベース テーブルを変更イベント ストリームに変換するために使用できるコネクタがいくつかあることがわかります。

このようにして、データベース テーブルのプライベート コピーが作成されます。データベースが変更されると、図に示すように、ユーザーは通知を受け取り、変更イベントに従ってプライベート コピー内のデータを更新します。

ここに画像の説明を挿入

[ストリームとテーブルを接続するトポロジ、外部データソースは不要]


ストリーム間接続

ストリームでは、上記の 2 つのストリームは同じキーによって分割されます。このキーは、2 つのストリームを結合するために使用されるキーでもあります。このようにして、user_id:42 のクリック イベントはクリック トピックのパーティション 5 に保存され、user_id:42 のすべての検索イベントは検索トピックのパーティション 5 に保存されます。ストリームは、これら 2 つのトピックのパーティション 5 からのイベントが同じタスクに割り当てられることを保証でき、このタスクは user_id:42 に関連するすべてのイベントを取得します。

Streams は、埋め込み RocksDB 内の 2 つのトピックの接続時間枠を維持するため、接続操作を実行できます。
ここに画像の説明を挿入

順番が狂ったイベント

順序どおりでないイベントや遅れて到着するイベントを処理するための重要なポイント:

  1. 順序どおりでないイベントを特定する: イベント時間を確認し、現在時刻と比較します。時間枠を超えている場合は、順序どおりでない、または遅れているとみなされます。
  2. 指定された時間枠内で順序が崩れたイベントを並べ替えます。たとえば、3 時間以内にイベントを並べ替え、3 週間を超えたイベントは破棄します。
  3. 時間枠内で順序どおりでないイベントを再配置する機能: バッチ処理とは異なり、ストリーム処理には「昨日のジョブを再実行する」という概念がなく、順序どおりでないイベントと新しいイベントを同時に処理する必要があります。
  4. 結果を更新する機能: 結果がデータベースにある場合は、put または update を使用して更新します。結果が電子メールで送信される場合は、更新方法が賢明である必要があります。
  5. 時間に依存しないイベントをサポートするフレームワーク: データフローやストリームなど、複数の集計時間ウィンドウを維持し、イベントを更新し、ウィンドウ サイズを構成できます。ウィンドウが大きくなるほど、ローカル状態メモリの要件も高くなります。
  6. Streams API の集計結果はトピック (通常は圧縮されたログ トピック) に書き込まれ、キーごとに最新の値のみが保持されます。集計ウィンドウの結果を更新する必要がある場合は、新しい結果をウィンドウに直接書き込み、以前の結果を上書きします。
    順序どおりでないイベントや遅れて到着するイベントを処理するには、次のことが必要です。
  1. 時間枠外のイベントを特定し、それらを削除または特別に処理します
  2. 時間枠内で順序が崩れたイベントの並べ替えウィンドウを定義します。この時間枠内で順序が狂ったイベントが並べ替えられます。
  3. シーケンス外のイベントを並べ替えて、定義された時間枠内で結果を更新する機能
  4. Dataflow や Streams など、時間に依存しないイベントとローカル状態管理をサポートするストリーミング フレームワークを選択します。
  5. 更新された集計結果を直接上書きし、圧縮されたログ トピックを使用して、結果トピックの無限の増大を回避します。

イベントの順序の乱れや遅れの到着はストリーム処理の一般的なシナリオですが、バッチの再計算には適していません。履歴状態を管理するために複数の時間枠を定義し、時間枠内で順序が崩れたイベントを再配置し、更新結果を直接上書きすることで、このような問題を効果的に解決できます。

Streams が提供するローカル状態管理、タイム ウィンドウ サポート、および圧縮されたログ トピックの書き込みにより、順序が乱れたイベントや遅れて到着するイベントを効率的に処理できます。さまざまな時間枠を構成することで、開発者はさまざまな粒度で状態管理とイベントの再配置を実装できます。

イベントの無秩序と遅延によってもたらされる課題は、履歴状態の管理と結果の更新にあります。Streams などのストリーミング フレームワークの出現により、開発者はこれらの根本的な問題にあまり注意を払うことなく、ストリーム処理アプリケーションのビジネス ロジックに集中できるようになりました。 。
ここに画像の説明を挿入

再処理

イベントを再処理するための 2 つのモード:

  1. ストリーム処理アプリケーションを改善し、新しいバージョンのアプリケーションは同じイベント ストリームを処理し、新しい結果を生成し、2 つのバージョンの結果を比較し、ある時点でクライアントの新しい結果ストリームを切り替えます。
  2. 既存のアプリケーションには欠陥があるため、修復した後、イベント ストリームを再処理して結果を再計算します。

最初のモードの実装:

  1. 新しいバージョンは新しいコンシューマ グループとして適用されます
  2. 入力トピックの最初のオフセットからイベントの読み取りを開始し、独自の入力ストリーム イベントのコピーを取得します。
  3. 結果フローを確認し、新しいバージョンのアプリケーションが進行状況に追いつき、クライアントを切り替えて新しい結果フローを適用します。
    2 番目のモードの課題:
  4. リセットは、再処理の入力ストリームの開始点に適用され、ローカル状態をリセットし、2 つのバージョンの結果の混乱を回避します。
  5. 前に出力ストリームをクリーンアップする必要がある場合があります
  6. Streams にはアプリケーションの状態をリセットするためのツールが用意されていますが、データ損失やクリーンアップによってエラーが発生するリスクがなく、異なるバージョンの結果を比較できるように、2 つのアプリケーションを条件付きで実行して 2 つの結果ストリームを生成する方が安全です。

イベント パターンを再処理するには、以下が必要です。

  1. イベント ストリームは、Kafka などのスケーラブルなデータ ストアで長期にわたります。
  2. 異なるバージョンのアプリケーションを異なるコンシューマ グループとして実行し、それぞれがイベント ストリームを処理して結果を生成します。
  3. 新しいバージョンのアプリケーションは、イベントを最初から読み取り、入力ストリームと結果の独自のコピーを構築し、現在のバージョンへの影響を回避します。
  4. 異なるバージョンからの結果を比較し、いつ切り替えるかを判断し、クライアントを新しい結果ストリームに慎重に切り替えます。
  5. 必要に応じて、既存の結果と状態をクリーンアップするか、リセット ツールを慎重に使用するか、並列モードを使用してクリーンアップを回避します。

イベント ストリームを長期保存すると、イベントを再処理し、アプリケーションのさまざまなバージョンの AB テストを行うことができます。現在実行中のアプリケーションをリセットするにはある程度のリスクが伴いますが、アプリケーションの複数のバージョンを並行して実行することでリスクを最小限に抑えることができます。

使用するモデルに関係なく、イベントの再処理には慎重な計画と実行が必要です。アプリケーションのさまざまなバージョンによって生成された結果ストリームを比較すると、新しいバージョンが期待される改善を達成したかどうかを明確に知ることができ、イベントとリリースを再処理するための基礎となります。

Streams のコンシューマ グループ管理とツールのサポートにより、イベントの再処理や AB テスト シナリオのパフォーマンスが向上します。異なるバージョンのアプリケーションを異なるコンシューマ グループに追加し、それぞれがイベント ストリームを処理して独立した結果を生成し、その後クライアントを慎重に移行することにより、これはより安全で信頼性の高い再処理イベント モードになります。

イベント ストリームの長期保持と信頼性の高い状態管理は、イベントの再処理の基礎です。さまざまなバージョンのアプリケーションの AB テストもこのメカニズムを通じて実行でき、ストリーミング アプリケーションの継続的な最適化と進化の可能性が得られます。

ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/yangshangwei/article/details/131008975