🪐
イベント駆動・バッチ処理の考慮点メモ
これは何?
イベント駆動やバッチ処理を行う際には通常の同期処理とは異なる観点を考慮する必要があるため、イベント駆動のアーキテクチャやバッチ処理を実装する際に考慮する点を整理する。
※著者がAWSしか経験がないため、AWSでの経験を元に記載していますが、AWS以外でもある程度同様のことが言えるかと思います。
1. イベント駆動アーキテクチャの考慮点
本当にイベント駆動にする必要があるのか
通常の同期実行に比べてイベント駆動は複雑性が増すため、トレードオフを理解した上で本当に必要かどうか再考する。
2種類のアーキテクチャのどちらを取るか
キュー (Queue)
- 受信側が定期的にキューにポーリングを行う。
- 1メッセージに対して1プロセスで処理。
トピック (Topic)
- 受信側が事前にトピックをSubscribeしておき、トピックにメッセージが来た直後に、Subscribeしているプロセスにメッセージが配信される。
- 1メッセージに対して複数プロセスがSubscribeできる。
ユースケース
- メッセージをまとめてバッチ処理したい場合
- キュー (溜まったキューをポーリングのタイミングで一気に処理できる)
- 受信側と送信側の稼働時間が異なる場合
- キュー (受信側のタイミングで処理を行える)
- 複数の処理を並列で処理したい
- トピック (1つのメッセージを複数のプロセスで処理できる)
- 受信側の数が増減する場合
- トピック
- 送信側は受信側の増減に影響されたく無いが、受信側は任意のタイミングで処理したい
- トピック + キュー
- 送信側は常に1つのトピックにメッセージを送信するだけで良く、最終処理を行うプロセスは自身の準備が出来たタイミングでキューからポーリングを行える
- 送信側に影響を与えることなく、最終処理を行うプロセスを増減出来る
- トピック + キュー
重複実行排除の必要性と実現方法
- 重複実行時のリスク検討 (本当に制御が必要か)
- プロデューサー側での実行制御方法
- FIFOキューの利用の検討
- 重複排除キーの検討
- 処理時間を見越した可視性タイムアウトの検討
- コンシューマ側での対策
- コンシューマ側の処理の冪等性の担保
実行順序保証の必要性と実現方法
- 実行順序が入れ替わった時のリスク検討 (本当に制御が必要か)
- 実行順序保証方法
- メッセージグループID
- イベント発火やコンシューマの処理時間に依存しないタイムスタンプの付与
エラーハンドリング
- エラーにより一度も実行されないことのリスク検討
- エラー時のリカバリ方法
- リトライ回数、リトライのアルゴリズム
- エンジニアへのエラー通知とDLQの再処理
- 通知などによるユーザーフィードバック
コンシューマが処理を開始するまでの時間
- イベント発火後、コンシューマがすぐに処理を開始することの是非の検討 (本当に制御が必要か)
- プロデューサ側が行なった処理(データストアへの反映など)の完了までのタイムラグなどを考慮し必要であれば遅延キューの検討
ロギング
- 処理の進捗状況を追跡できる
- 詳細なエラー情報を記録しているか
- 処理の失敗箇所を特定できるか
- プロデューサー側とコンシューマ側での紐付けなど
結果整合性の担保
- ユーザーの行なった操作と操作の結果の整合性
- 途中で処理が失敗した場合の適切なエラーハンドリング
- あるコンポーネントでの処理結果のデータの状態と、別のコンポーネントでの処理結果のデータの状態の整合性
各プロセスでのパフォーマンスやクォータ
- 処理を担当するプロセスのいずれかがボトルネックになって処理が滞ったり、どこかのプロセスが停止したりしないか
- 大量の処理を行う際にAWSなどのサービスクォータに引っかからないか(これはバッチ処理の場合も同様)
2. バッチ処理の考慮点
大量データ処理時のパフォーマンス
- 既存ユーザーへの影響
- テーブルロック、行レベルロック
- DBのCPU、メモリ負荷
- 処理のタイムアウトのリスク
- 並列実行の検討
- 顧客ごとにプロセスを分けて並列実行するなど
- バッチの実行タイミング
- 実行タイミングが他のバッチ処理と被ると処理対象(例えばDB)のパフォーマンスに影響しないか
バッチ処理実行時にユーザー操作が発生する場合の対応
- 処理実行中にユーザー操作を完全にブロックする必要があるか
- ブロック無しで実施できないか
顧客間のデータ分離
- 複数企業データを一度に処理するため異なる顧客間のデータが混在しないよう細心の注意を払う
エラー発生時のリカバリ
- 全部成功 or 全部失敗 (All or Nothing) を保証するか
- 複数回実行してもデータ不整合は発生しない。ただし、処理全体でトランザクションを張る必要があるのでトランザクションが長くなる可能性がある
- 失敗した対象だけを後から再処理するか
- トランザクションを分割することで短くすることは出来るが一部失敗時に備えて未完了の処理対象が分かるようにしておく必要がある
- メール送信のようなロールバック不可の処理はこちらでやらざるを得ない
ロギング
- 処理の進捗状況を追跡できるか
- 詳細なエラー情報を記録しているか
- 処理の失敗箇所を特定できるか
Discussion