ここでは、イベントソーシングについて次の観点で説明します。
イベントソーシングとは
イベントソーシング(Event Sourcing)とは、データの状態を直接保存するのではなく、システム内で発生した全てのイベントを記録する設計アプローチです。
通常のシステムの場合、ユーザーや他のシステムがシステムを操作することで、システムがデータを処理して、その状態をデータストアに記録します。
なので、状態管理のシステムの場合、データのある時点の状態を記録し管理します。
それに対して、イベントソーシング(Event Sourcing)の場合、ユーザーや他のシステムがシステム対して行った操作をイベントとして記録します。
なので、イベントを管理するシステム(イベントソーシング)の場合、データの状態遷移の過程を記録し管理するので、必要に応じて特定の時点の状態を再構築(再現)することができます。
イベントソーシングのメリットとデメリット
次に、イベントソーシングのメリットとデメリットを状態管理のシステムと比較しながら見ていきましょう。
イベントソーシングのメリット
- 独立性の向上
状態管理のシステムを参照するシステムは、特定の時点の状態に依存するのでリアルタイムに同期をとる必要があり、システム間を密結合にします。
一方、イベント管理のシステムを参照するシステムは、特定の時点の状態に依存せず、イベントのリストさえ取得できれば、必要に応じて(非同期で)特定の時点の状態を再構築することができるので、システム間の依存度を下げ、システムの独立性を上げることができます。
- 拡張性の向上
イベントはログとして保存されるため、特定の状態を管理するノードが複数に分散されていても、イベントのリストさえあれば、どのノードでも状態を再現できます。これにより、トラフィックが増加した場合や、データ量が増えた場合でも、複数のサーバーにワークロードを分散してスケールアウトが可能です。
一方、状態管理のシステムを拡張する場合、拡張したすべてのシステムで同一の状態を保つことは困難です。
さらに、そのシステムを参照しているシステムがある場合、拡張したシステムのどれをアクセスしても一貫して同じ状態を返すようにすることも困難です。 - 可用性の向上
高可用性は、システムが障害時にもダウンタイムを最小限に抑えつつ動作を継続できる能力です。
イベントストアは複数のノードにレプリケーション可能です。万が一、あるノードがダウンしても他のノードがイベントを保持しているため、すぐに別のノードにフェイルオーバーし、高可用性を保つことができます。
一方、状態管理のシステムの場合、複数のシステムで同じ状態を保つことが困難なので、単一障害点になりやすくなります。 - 追跡可能性の向上
イベント管理のシステムは、状態遷移の過程を記録し管理するので、必要に応じて特定の時点の状態を再構築(再現)することができます。
なので、過去の状態遷移の過程を追跡することができ、次のような効果を得ることができます。- 監査とコンプライアンス
金融業界や医療業界など、厳格な規制が存在する分野では、データの変更履歴をすべて追跡・保存する必要があります。
監査の際に、ある取引や医療記録がどのように変更され、誰がいつそれを行ったのかを正確に再現することができます。
例えば、ある口座の残高が特定の日時にどのように変更されたのかを確認し、その正当性を証明するために過去の状態を再現できます。 - デバッグとエラー解析
ある問題が発生した時点のシステム状態を再現することで、どのイベントが原因でエラーが発生したのかを突き止めることができます。
例えば、特定の顧客の注文がなぜ誤処理されたのかを再現し、エラーの原因を特定するために、当時のイベントシーケンスを確認します。 - ビジネスプロセスの検証・分析
ある注文がどの時点で承認され、どのタイミングで出荷指示が出され、その後どのように顧客に届いたか、という一連のプロセスをイベントを使って再現することで、業務フローを振り返り改善点を見つけることができます。 - ユーザートラッキングと行動解析
ユーザーがどのような操作を行った結果、特定の商品をカートに入れ、購入を完了したのかというユーザーの操作履歴を再現し行動を解析をすることができます。 - 予測モデルの精度向上
予測モデルを訓練するために、特定の時間範囲のデータが必要な場合があります。
イベントソーシングではその期間内の状態遷移を正確に再現できるためより精度の高い予測モデルを構築することができます。
- 監査とコンプライアンス
イベントソーシングのデメリット
- 複雑性の増大
すべての状態変化をイベントとして管理するため、システムの設計と実装が複雑になります。イベントストアの管理、イベントの再生、イベントバージョン管理など、従来のCRUDアプローチよりも多くの考慮事項が必要です。 - データの整合性
イベントが非同期に処理される場合、データの最終的な整合性(Eventual Consistency)を前提とすることが多くなり、即時整合性が求められる場合には適さないことがあります。 - ストレージの膨張
すべてのイベントを保存するため、ストレージが膨大になる可能性があります。データが長期間に渡る場合や頻繁に更新されるシステムでは、ストレージコストが増大します。 - イベントの再生に時間がかかる
特定の時点の状態を再現するには、イベントの再生が必要です。イベント数が増加すると、この再生プロセスに時間がかかる可能性があり、特に起動時やリカバリ時にパフォーマンスに影響を与えることがあります。 - イベントスキーマの進化
時間の経過とともにイベントスキーマが進化する必要がありますが、古いイベントと新しいイベントが混在する可能性があり、スキーマの互換性やマイグレーションが課題となります。
例えば、顧客注文のイベントに新しいフィールド(例えば「割引情報」)が追加される場合があります。
古いスキーマ: 割引情報がない注文イベント
新しいスキーマ: 割引情報を含む注文イベント
CQRSとイベントソーシング
のコマンド処理側にイベントソーシングを適用すると、そのメリットを活かすことができるので効果的です。
クエリ処理では、コマンド処理からイベントを非同期で受け取り、クエリに必要なある時点のスナップショットを作成するようにします。
イベントソーシングを介したシステム間連携は、CQRSだけでなく、バッチ処理にも適用することができます。
次の図は、サービスイベントを管理するイベントソーシングのシステムから、サービスイベントを受け取った料金計算システムが、料金計算に必要なワークデータを作成し、それに基づいて料金計算を行い結果をイベントストアに記録するという例です。
料金計算システムに記録された料金卦算結果イベントは、請求管理システムの請求書発行に利用されます。
なお、マイクロサービスアーキテクチャを適用すると、各システムがサービス管理サービス、料金計算サービスというマイクロサービスになります。
DDDとイベントソーシング
ヴォーン・ヴァーノンの実践ドメイン駆動設計という書籍では、ドメイン駆動設計(DDD)の構成要素である集約ごとにイベントストアを設け、イベントソーシングを実現することを推奨しています。
また、Sam Newmanのマイクロサービスアーキテクチャという書籍では、DDDの集約ごとにマイクロサービスを設けることにより、マイクロサービスの一貫性を保ちやすく、依存関係を最小限にできると説明しています。
集約は、ドメインオブジェクトのライフサイクルを管理する単位であるので、この単位にコマンド処理のマイクロサービスを設け、イベントソーシングによって集約のイベントを管理することで、イベントソーシングのメリットである独立性、拡張性、可用性などを高めることができます。
なお、集約の状態を変化させる操作など、特定のドメインにおける重要な出来事のことをドメインイベントといいます。
複数のマイクロサービスを跨いだ分散トランザクションは、Sagaによって管理することができます。
[…] ;マンド処理のマイクロサービスにイベントソーシングを適用します。 […]