
Event Sourcing(イベントソーシング)は、「データの現在状態」ではなく「状態を作り出した出来事(イベント)の履歴」を保存するアーキテクチャパターンです。
通常のアプリでは「最新の状態」をDBに保存しますが、Event Sourcingでは「その状態に至るイベント(出来事)」を保存します。
要するに、最終値(最新状態)を1レコードで更新するのが通常のところ、複数発生するログを全て保持するようにするという履歴型データ保持形式です。
例)
[通常]
- 残高 10000
[Event Sourcing]
- 入金 +5000
- 出金 -2000
- 入金 +7000
典型的な構成イメージ
Command
└ Aggregate
└ Event Store
↓
Projection (View DB)
↓
Query / API
・Command:ユーザー操作(例:入金コマンド)
・Aggregate:ビジネスロジック(ルールチェックや状態変更)
・Event Store:イベント(出来事)を保存
・Projection:イベントを反映して「現在状態」を再構築
サンプルコード
class BankAccount {
constructor() {
this.events = []
}
deposit(amount) {
this.record({ type: 'Deposited', amount })
}
withdraw(amount) {
this.record({ type: 'Withdrawn', amount })
}
record(event) {
this.events.push({ ...event, date: new Date() })
}
get balance() {
return this.events.reduce((sum, e) => {
return e.type === 'Deposited' ? sum + e.amount : sum - e.amount
}, 0)
}
}
const account = new BankAccount()
account.deposit(5000)
account.withdraw(2000)
account.deposit(7000)
console.log(account.balance) // 10000
console.log(account.events) // 履歴がすべて残っている
よく組み合わせられる技術
・CQRS(Command Query Responsibility Segregation)
・Kafka / RabbitMQ(イベントストリーム)
・EventStoreDB / DynamoDB Streams
・スナップショット機構(高速再構築用)
メリット
・すべての履歴が残る
いつ・誰が・何をしたのかを完全に再現できる。
・監査・分析に強い
「なぜこの状態になったか」が後から追跡できる。
・過去の状態を再構築できる
特定時点の状態を再生(replay)して検証できる。
・CQRSと相性が良い
読み取り系と書き込み系を分けることで、高速なクエリと柔軟な集約が可能。
デメリット
・実装が複雑になる
イベントの再生・整合性管理・スナップショット処理が必要。
・スキーマ変更が難しい
イベント構造を変更すると過去データへの影響が出る。
・即座に「最終状態」を取得しにくい
すべてのイベントを適用しないと現在の状態がわからない。
あとがき
「Event Sourcing」は、“データの履歴”をファーストクラス市民にする設計思想です。
状態を保存するのではなく、“物語”を保存するような感じ。
どちらかというと、データベースへの保持ルール的なパターンです。
ただ、一時的な保持として、Webプログラミング特有のCookieやLocalStorageなどのキャッシュ保持にも使えるテクニックなので、
使いこなせると、安定したSPAなどの開発ができるというイメージが持てますね。
0 件のコメント:
コメントを投稿