私は最近、職場で適用する必要があるかもしれないので、CQRS / ESに飛び込み始めました。多くの問題を解決するため、私たちのケースでは非常に有望です。
ES / CQRSアプリが、単純化された銀行のユースケース(出金)にコンテキスト化されたように見える方法についての大まかな理解をスケッチしました。
要約すると、Aがお金を引き出した場合:
- コマンドが発行されます
- 検証/検証のためにコマンドが引き渡される
- 検証が成功した場合、イベントはイベントストアにプッシュされます
- アグリゲーターはイベントをデキューして、集約に変更を適用します
私が理解したことから、イベントログは真実の源であり、FACTSのログであるため、それから予測を導き出すことができます。
さて、この壮大な計画の中で私が理解できないのは、この場合に何が起こるかです:
- ルール:残高をマイナスにすることはできません
- 人Aのバランスは100eです
- 人Aは100eのWithdrawCommandを発行します
- 検証に合格し、100eイベントのMoneyWithdrewEventが発行されます
- その間に、人Aは100eの別のWithdrawCommandを発行します
- 最初のMoneyWithdrewEventはまだ集約されていなかったため、検証は合格です。これは、集約に対する検証チェック(まだ更新されていないため)
- 100eのMoneyWithdrewEventがもう一度発行されます
==>残高が-100eで、ログに2つのMoneyWithdrewEventが含まれる一貫性のない状態です
私が理解しているように、この問題に対処するにはいくつかの戦略があります。
- a)集約バージョンIDをイベントストアにイベントとともに配置し、変更時にバージョンの不一致がある場合、何も起こらない
- b)検証層が何らかの方法で作成する必要があることを意味する、いくつかのロック戦略を使用する
戦略に関する質問:
- a)この場合、イベントログはもはや真実の源ではありません。どう対処するのですか?また、引き出しを許可することは完全に間違っていましたが、クライアントに戻りましたが、この場合はロックを使用する方が良いですか?
- b)ロック==デッドロック、ベストプラクティスに関する洞察はありますか?
全体として、並行性の処理方法に関する私の理解は正しいですか?
注:同じ人がこのような短い時間枠で2倍のお金を引き出すことは不可能であることを理解していますが、詳細に迷子にならないように簡単な例を取り上げました