CQRSのコストとトレードオフについて

どんな強力なツールでもそうであるように、CQRS(Command Query Responsibility Segregation)は無料で使えるわけではない。CQRSにはコスト(手間という意味)が伴うが、その利点も多い。

従来のアーキテクチャより複雑だと批判されることもあるCQRS/ES(Event Sourcing)だが、実際にはシンプルに実装できる部分もある。

CQRSにおけるモデルの分割

CQRSではシステムを分割し、書き込みモデルと読み込みモデルを独立させる。例えば、ホテルの部屋を予約するシステムを考えると、部屋を予約する・宿泊人数を変更する・予約をキャンセルするなどの行為は書き込みモデル(集約ルート)に該当し、顧客別予約・ホテル別予約などの情報は読み込みモデルになる。この分割により、各オブジェクトはより単純化されるが、システム全体としての複雑さは増す。これは、CQRSにおける重要なトレードオフの一つである。

非CQRSな伝統的なシステムでは、読み込み時にテーブル結合やビューを用いるため、読み込みモデルは書き込みモデルと密接に結合している。これは、読み込み操作が書き込み操作で使用されるデータベースのテーブル構造やビューに依存しているためである。CQRSでは、このような密接な結合を解消し、書き込みモデルの変更が読み込みモデルに影響を与えることなく、システムの柔軟性やスケーラビリティを高めることができる。

結果整合性の問題

CQRSにおいて、結果整合性の問題はよく話題になる。しかし、結果整合性の問題はCQRS固有のものではない。リプリケーションを使用するRDBシステムでは、伝搬遅延により、リードレプリカから取得したデータは最新ではない可能性がある。このため、更新が続く限り、システムは常に結果整合性の状態にある。また、テーブル結合を行う際も、片方のテーブルのデータが古い可能性がある(結合対象のトランザクションが異なる場合)。これらは、CQRSを採用する際にも考慮すべき重要な要素である。

CQRSのトレードオフ

いうまでもないが、CQRSの採用は、要件や目標に対する妥当性が前提となる。多くの要素を考慮する必要があるが、これにより本質的な問題に集中できる。

デメリットとしては、コマンド、コマンドリプライ、イベント、リードモデル、集約などの概念が増え、システムが複雑化することが挙げられる。これは避けられないが、クラスベースの設計では簡略化することが可能である。

また、書き込みモデルには書き込みのスケールアウトとCDC(Change Data Capture)が可能なデータベースを、読み込みモデルには多様な問い合わせに対応できるデータベースを採用することで、システムの非同期性を管理し、UIへの影響を最小限に抑えることができる。

イベントソーシングを採用する場合、データベースには状態が存在せず、イベントログが使用される。状態はイベント集合から動的に構築され、アプリケーション内で管理される。古いイベントの形式は変更できず、新しいバージョンのイベントを追加する必要がある。また、イベント履歴(ジャーナル)と読み込みモデル用の追加ストレージが必要となる。

コスト軽減のためのツール

これらの課題は、akka、apache pekko、proto.actorなどのライブラリやフレームワークを使用することで軽減できる。

上記はアクターモデルがベースなので、クラスベースでシンプルにやってみたい方は、拙作のライブラリがおすすめである。

---

CQRSは上記のようなコストを伴うが、それに見合う価値を提供する。万能な解決策としてではなく、目的に合わせて適切に選択することが重要である。

併せて読みたい

@j5ik2o
歳をとっても霜降り肉!をモットーにしております