見出し画像

ストリーム処理とバッチ処理の比較と運用における注意点

1. ストリーム処理とバッチ処理の基本概念

1.1 バッチ処理とは

バッチ処理は、一定期間に蓄積されたデータを一括で処理する方式です。典型的には、1日、1時間、またはそれ以上のスパンでデータを集め、その後一度に処理を行います。

バッチ処理のメリットは、データを一気に処理するためスケーラビリティが高く、リソースの使用効率も比較的高いことです。
また、システムの停止やエラーが起きた際にリカバリーが比較的容易です。しかし、リアルタイム性がないため、即時反応が求められるケースには不向きです。

バッチ処理のメリット:

  • 大量のデータを一括で処理できる。

  • 処理の実行タイミングを自由に調整できる。

  • システム障害やエラーのリカバリーが容易。

バッチ処理のデメリット:

  • リアルタイム処理ができない。

  • 大量のデータが一度に処理されるため、ピーク時の負荷が高くなる可能性がある。

1.2 ストリーム処理とは

ストリーム処理は、データが生成され次第、即座に処理を行う方式です。例えば、センサーデータやユーザーのクリックデータなど、リアルタイムで得られる情報を瞬時に分析・処理することができます。
このアプローチは、レイテンシー(遅延)を最小化し、即座にフィードバックを提供することが求められるシステムにとって非常に重要です。たとえば、広告配信システムやリアルタイム監視システムなどが代表的なユースケースです。

ストリーム処理のメリット:

  • リアルタイムにデータを処理できる。

  • レイテンシーが低く、即座にフィードバックを得られる。

  • 小さなデータの断片を継続的に処理するため、バッチ処理と比較してピーク時の負荷を平滑化できる。

ストリーム処理のデメリット:

  • 常に動作しているため、システムのリソース使用が高くなる可能性がある。

  • エラーハンドリングやシステム障害時のリカバリーが難しい場合がある。

  • 一度処理したデータの再処理がバッチ処理に比べて複雑。

2. ストリーム処理の運用上の注意点

ストリーム処理はリアルタイム性が強みですが、その分、運用には慎重な管理が必要です。以下では、特にストリーム処理の運用において考慮すべき重要なポイントをいくつか挙げ、それぞれの対策について説明します。

2.1 エラーハンドリング

ストリーム処理では、リアルタイムで大量のデータを処理するため、エラーが発生する可能性が高くなります。例えば、ネットワークの障害や、データ形式の不整合などがその代表です。バッチ処理と異なり、ストリーム処理ではデータを後から再処理するのが難しい場合が多いので、エラーハンドリングの仕組みを慎重に設計する必要があります。

対策:

  • データの再試行: エラーが発生したデータをキューに戻し、再試行できる仕組みを作ります(デッドレターキュー)。

  • エラーログの保持: エラーが発生したデータや処理内容を詳細に記録し、後から検証できるようにします。

  • 部分的なリトライ: 全体を停止させるのではなく、エラーが発生した部分のみを再処理できるようにすることで、システム全体の停止を防ぎます。

2.2 データの順序保証

ストリーム処理では、データが生成された順序で正確に処理されることが重要な場合があります。しかし、分散システムではネットワーク遅延やサーバー間の処理の違いにより、データの順序が崩れることがあります。

対策:

  • タイムスタンプの付与: 各データにタイムスタンプを付与し、処理時にそれに基づいてデータの順序を調整する仕組みを導入します。

  • ウィンドウ処理: 一定期間ごとにデータを集約し、そのウィンドウ内で順序を保ちながら処理を行う方法を取ります。

2.3 データ重複の防止

ストリーム処理では、同じデータが複数回処理される「重複処理」が発生するリスクがあります。これはネットワークエラーや、データの再試行時に起こりやすい問題です。データの重複は、特に集計処理などで誤った結果を導く可能性があるため、厳重に対策を講じる必要があります。

対策:

  • データの一意識別: 各データにユニークなIDを付与し、処理の際に重複を検出して無視する仕組みを作ります。

  • 冪等性: 同じデータが複数回処理されても結果に影響を与えないよう、処理に冪等性を持たせた設計にします。

3. バッチ処理とストリーム処理のハイブリッドアプローチ

バッチ処理とストリーム処理はそれぞれ異なる強みを持っていますが、現実のシステムでは両者を組み合わせることが多くあります。特に、定期的な集計処理や履歴データの管理にはバッチ処理が適しており、一方でリアルタイムなフィードバックやアラートにはストリーム処理が有効です。このようなハイブリッドアプローチを取ることで、システム全体の柔軟性と効率性を向上させることができます。

3.1 Lambdaアーキテクチャ

Lambdaアーキテクチャは、バッチ処理とストリーム処理を組み合わせたアーキテクチャの一例です。データがリアルタイムで処理される一方で、定期的なバッチ処理で大規模なデータ集計も行われます。このアプローチにより、ストリーム処理で得られる即時の結果と、バッチ処理で得られる正確な集計結果をバランスよく利用することが可能です。

lambda architecture

(補足)Kappaアーキテクチャ

Kappaアーキテクチャは、Lambdaアーキテクチャの簡略化されたバージョンで、すべてのデータ処理をストリーム処理で行い、バッチ処理を廃止するアプローチです。このモデルでは、過去のデータも含め、すべてのデータをリアルタイムで処理し続けることで、一貫性の高いデータ処理を実現します。

しかし、構築・運用が想像以上に難しかったり、コストが高くなってしまうことが原因で多くの企業では採用されにくいようです。

kappa architecture

運用上のポイント:

  • リアルタイムでの一貫したデータ処理を行うため、ストリーム処理のスケーラビリティと耐障害性を向上させる必要があります。

  • 長期間にわたるデータの再処理が必要な場合には、適切な保存と再処理メカニズムを確保する。

4.理由が無ければバッチ処理を選択する

私の独断と偏見にはなりますが、2024年8月時点ではバッチ処理を選択することが望ましいケースが多いです。特に理由が無ければ、ストリーム処理ではなく、バッチ処理を選択すると良いと思います。

以下に、この理由を書きます。

4.1 コスト効率

バッチ処理は、特定の時間にデータを一括して処理するため、必要なリソースを効率的に割り当てられます。処理時間をオフピーク時(リソース需要が少ない時間帯)にスケジュールすることで、サーバーのコストを削減することが可能です。

ストリーム処理は常に動作し続けるため、データの流入が少ない時間帯でもリソースを消費し続けます。結果的に、ストリーム処理はスケーラブルなインフラと継続的なリソースの確保が必要になるため、運用コストが高くなる傾向があります。

4.2 複雑さと管理コスト高

ストリーム処理ではリアルタイムにデータを処理するため、データフローの設計が複雑であり、システムのモニタリングやエラーハンドリング、データの順序保証など、運用上の管理が難しくなります。
これに対して、バッチ処理は設計が比較的単純で、エラーが発生しても後からリトライしたり、再処理したりすることが容易です。特にビジネスがリアルタイムの要件を必ずしも必要としない場合、バッチ処理のほうが管理負担が軽減されます。

4.3 ユースケースに応じたリアルタイム性の必要性

ストリーム処理はリアルタイム性が求められるユースケースに最適ですが、ほとんどのビジネスアプリケーションでは、データの処理が1日数回や数時間おきに行われれば十分なことが多いです。

例えば、日次の売上集計や顧客分析などは、バッチ処理で十分に対応できるケースが多いです。リアルタイムでのフィードバックや即座のアクションが求められないケースでは、運用コストや複雑さを考慮して、バッチ処理が合理的な選択となります

5. バッチ処理の特性と限界

頻繁にUPDATEされるレコードを扱う場合、バッチ処理ではすべての変更を適切にキャプチャできないという問題が発生する可能性があります。バッチ処理はデータを一定の時間ごとにまとめて処理するため、その間に発生した複数のUPDATE操作を全て把握することが難しくなります。

以下に、この問題に対する具体的な理由と対策を説明します。

5.1 タイミングの問題

バッチ処理は、あるタイムウィンドウ(例:毎日、毎時間など)にデータを一括で処理します。このため、ウィンドウの間に発生したデータの更新(UPDATE)は、最新の状態しか反映されず、過去の変更履歴が失われることがあります。

例えば、1つのレコードが4回更新された場合、バッチ処理は最後の更新だけをキャプチャし、途中の変更は無視される可能性があります。

高頻度の変更をキャッチできない

5.2 状態管理の不足

通常のバッチ処理では、レコードの最新のスナップショット(現在の状態)を取得することが一般的です。しかし、これでは更新の履歴を記録し、すべての変更を追跡することは難しいです。

後述するイミュータブルモデルを採用したり、CDCのような仕組みを導入する必要が出てきます。

6. 頻繁な更新をキャプチャするための対策

6.1  チェンジデータキャプチャ(CDC)

  • CDC (Change Data Capture) という技術は、データソースで発生したINSERT、UPDATE、DELETEなどの変更をリアルタイムまたはほぼリアルタイムに検出し、保存するための手法です。これにより、バッチ処理のウィンドウ内で発生したすべての変更をキャプチャすることができます。具体的には、データベースのトランザクションログを監視し、変更があったデータだけを追跡して記録します。

  • 実装例:

    • Debezium: Apache Kafkaと連携してデータベースの変更履歴をキャプチャできるCDCツール。

    • Spanner Change Stream: Cloud Spanner データベースのデータ変更(挿入、更新、削除)をほぼリアルタイムで監視してストリーミングします。

6.2 イミュータブルデータモデル

  • イミュータブル(不変)データモデルを採用すると、レコードの更新を直接上書きするのではなく、新しいバージョンのレコードを追加して、すべての更新履歴を保存します。これにより、バッチ処理を行った際にも、すべての変更がデータベースに残り、どのタイムウィンドウであっても変更履歴を追跡できます。

  • 実装例:

    • インサートオンリーパターン: 更新時にデータを上書きせず、新しい行として追加する。この場合、最新のレコードを取得するクエリが必要になるが、すべての更新履歴が保持されます。

インサートオンリーパターン

6.3 ストリーム処理との併用

  • Lambdaアーキテクチャのように、バッチ処理とストリーム処理を組み合わせることで、頻繁に更新されるデータをリアルタイムにキャプチャしながら、バッチ処理で正確なデータの整合性を保つことができます。

  • ストリーム処理はデータの変更が発生するたびに即座に反映できるため、バッチ処理でキャプチャしきれない変更を補完します。

まとめ

バッチ処理は一定期間に蓄積されたデータを一括で処理し、スケーラビリティやコスト効率に優れていますが、リアルタイム性が求められる場面には不向きです。

ストリーム処理はリアルタイムでデータを処理し、即時のフィードバックが必要な場合に適しています。しかし、リソース消費が多く管理が複雑です。

現状では要件が無ければ、できるだけバッチ処理を選択することが良い気がします。そして、リアルタイム要件があるのであれば、ストリーム処理を採用します。ハイブリッドアプローチ(Lambdaアーキテクチャ)により、両者の利点を活かすことも望ましいです。

関連書籍

データアーキテクチャの設計やETLパイプライン、データモデリングについての記載があります。この本の内容を理解できれば、データエンジニアリング業務で必要な単語や概念は一通り浚うことができるはず。

データモデリングを学ぶ1冊目には丁度良い本です。分析基盤だけでなく、基幹系システムで数十年間、不変な技術として存在し続けています。


この記事が気に入ったらサポートをしてみませんか?