CQRSに対する批判的見解

Command Query Responsibility Segregation(CQRS, コマンドクエリ責務分離)をもっと大きく,アーキテクチャ的コンテキストで眺めてみると,他にも利用可能なアーキテクチャスタイル,例えばEvent-Driven Architecture(EDA, イベント駆動アーキテクチャ)やパブリッシュ・サブスクライブといったものが存在することに気付く。さらには従来的なデータベース技術でも,同じ問題をずっと簡単な方法で解決することが可能だ – Udi Dahan氏は,CQRSへの別のアプローチに関して,このような意見を述べている。CQRSが本当に必要であったとしても,これまでのCQRSに比べてはるかに少ない可動部品で,目標の大部分を達成可能な別の方法がある,と氏は主張する。

CQRSアプローチが選択される理由のひとつはスケーラビリティである – Greg Young氏と並んでCQRSの最前線にいる人物のひとりであるDahan氏は,ユーザとの会話の中でCQRSをこのように評じている。読み込み処理が大量に発生する場合,読み込みと書き込みを分離することでクエリのスケーリングが可能になる。 しかしDahan氏は,ほんのわずかな,あるいはまったくコードを書かなくても,読み込み/書き込み処理を分離可能な技術がすでに存在する,開発者はそれに気付くべきだ,と主張する。もうひとつの理由としてDahan氏が考えるのは,世界規模で多数の講演が行われていることによる,CQRSを採用すべき,という社会的プレッシャだ。

読み込み中心の環境でスケーラビリティを達成する,もうひとつの手段が,マスタ/スレーブレプリケーションだ。データを更新するひとつのマスタと,すべての変更を複製するひとつ以上のスレーブで構成する。古くから存在し,どのデータベースでもサポートされている機構だが,書き込みと読み込みを分離しているという意味から,これもCQRSの一種であるとDahan氏は定義する。クエリ結果構築に複雑な表結合を利用している場合,このレプリケーションでは,解決不可能なレイテンシ問題が発生する可能性があるが,スループット的な問題であればスレーブの数を増やすことで解決可能だ,と氏は指摘している。

スケーラビリティ問題を解決する別のソリューションとして氏が提案しているのは,ひとつのテーブル内のデータをユーザ名などを使用して複数のデータベースインスタンスに分散するという,シャーディングあるいはデータベースパーティショニングと呼ばれる手法だ。この方法によるメリットのひとつは,複数のマスタが存在することだ。コマンドとクエリ,両方の面でスケーリングが可能になる。パーティショニングは多くのデータベースにおいて,初期状態で利用可能になっているため,非常にシンプルなコードで実装することができる。氏はさらに,複数マスタ構成はクロスレコードトランザクションでは機能しないため,ソリューションドメイン内でのビジネスドメインは同じパーティショニングであることが必要な点を指摘している。

CQRSアプローチが適した場合がある,と氏が考える状況のひとつは,極めて高く局所的な負荷を持った,非常に競合の多いドメインである。データベースのひとつないしごく少数のレコード上で,多数の要求が競合している状況がこれに当たる。障害の発生するシナリオのひとつは,同時実行に関する例外発生によって多数のトランザクションがフェールし始め,データベース接続とクライアント要求がロックされることによって,巨大なボトルネックが形成される,というものだ。スケーラビリティのテストでは一般的に少数のレコードではなく,多数のレコードに対して多数の要求を実行することでロードを発生させる場合が多いため,このようなケースは見落とされがちだ。CQRSを完璧に実装したとしても,クエリ側でボトルネックが現れるだろう。バックグラウンドプロセスが十分な速さで更新処理をできないため,クエリモデルはさらに遅れることになる。

この競合問題に対するDahan氏のソリューションは,非ブロックで追加オンリー,すなわち接続の影響を受けないイベントベースのモデルに移行することだ。しかしながらこの方法は,新たな問題を導く可能性がある。製品在庫数が十分でない限りオーダを処理してはならないというような,ビジネスルールが阻害されるためだ。そのため,このソリューションでは,よりフレキシブルなプロセスと,要件の変更可能性が必要になる。先程のオーダの例を使うならば,在庫チェックを行わずにオーダを受付けられるようにしなければならないのだ。オーダが処理される段階になって在庫から製品を引き当てられなくなったらどうするか,そのような状況について予め決めておく必要がある。