web-dev-qa-db-ja.com

イベントソーシングとCQRSを使用するデメリットは何ですか?

イベントソーシングとCQRSは素晴らしいものです。大きなデータ移行プロジェクトがない限り、開発者がアプリケーションの存続期間中に作業しなければならない、事前にモデル化された1つのデータベースに悩まされることがなくなるためです。 CQRSとESには、すでにインターネット上にあるイベントストア、監査ログなどのスケーリングのような他の利点もあります。

しかし、欠点は何ですか?

小さなデモアプリを調査して作成した後に私が考えることができるいくつかの欠点があります

  1. 複雑: ESは複雑だと言う人もいます。しかし、複雑なアプリケーションを持つことは、クエリ言語(複数の結合、インデックスなど)を使用して非常に制限されたクエリしか実行できない複雑なデータベースモデルよりも優れていると思います。 Scalaのような一部のプログラミング言語には、非常に柔軟で非常に複雑な集約を生成できる非常に豊富なコレクションライブラリがあり、Apache Spark分散コレクションをクエリします。ただし、データベースは常にそのクエリ言語機能に制限され、データベースの分散は分散アプリケーションコードよりも困難です(別のインスタンスを別のマシンにデプロイするだけです!)
  2. ディスク領域の使用率が高い:イベントストアは、イベントを格納するために大量のディスク領域を使用することになります。しかし、数週間ごとにクリーンアップをスケジュールし、スナップショットを作成することができます。将来、古いイベントが必要になった場合に備えて、外部のHDにローカルで履歴イベントを保存できますか?
  3. メモリ使用量が多い:すべてのドメインオブジェクトの状態がメモリに保存されるため、増加する可能性がありますRAM使用量とすべての負荷が高いRAMは。大きな問題!!私は貧しいからです!これに対する解決策はありますか?メモリに状態を保存する代わりにSqliteを使用できますか?アプリケーションに複数のSqliteインスタンスを導入することで、物事をより複雑にしていますか?
  4. 起動時間が長い:イベントの数によっては、障害発生時またはソフトウェアアップグレードの起動が遅い。しかし、これを解決するためにスナップショットを使用できますか?
  5. 結果整合性:一部のアプリケーションに問題があります。 FacebookがCQRSでイベントソーシングを使用して投稿を保存し、facebookのシステムがどれほど忙しいかを検討していて、投稿を投稿した場合、翌日のfb投稿が表示されると想像してみてください。
  6. イベントストア内のシリアル化されたイベント:イベントストアは、イベントをシリアル化されたオブジェクトとして保存します。つまり、イベントストア内のイベントのコンテンツをクエリすることはできません。また、今後イベントに別の属性を追加することはできません。解決策は、シリアル化されたイベントの代わりにJSONオブジェクトとしてイベントを格納することでしょうか?しかし、それは良い考えですか?または、イベントを追加して、元のイベントオブジェクトへの変更をサポートしますか?

ここで取り上げた欠点について誰かがコメントしてください。間違っている場合は訂正して、他に見逃したかもしれない提案がありますか?

33
hajime

これが私の見解です。

  1. CQRS + ESは、豊富なドメインオブジェクト、単純なデータモデル、履歴追跡、同時実行性の問題の可視性、スケーラビリティなどにより、複雑なソフトウェアシステムでの作業を大幅に簡素化できます。システムについて異なる考え方をする必要があるため、資格のある開発者を見つけるのは難しいかもしれません。ただし、CQRSを使用すると、開発者間での責任の分離が簡単になります。たとえば、ジュニアデベロッパーは、ビジネスロジックに手を加える必要なく、純粋に読み取り側で作業できます。

  2. データのコピーには、確かにより多くのディスク容量が必要です。しかし、最近のストレージは比較的安価です。問題が発生した場合に備えて、ITサポートチームがより多くのバックアップを実行し、システムを復元する方法を計画する必要があります。ただし、最近のサーバー仮想化により、ワークフローはより合理化されています。また、モノリシックデータベースを使用せずにシステムに冗長性を作成する方がはるかに簡単です。

  3. メモリ使用量の増加は問題とは見なしていません。ビジネスオブジェクトのハイドレーションはオンデマンドで実行する必要があります。オブジェクトは、すでに永続化されているイベントへの参照を保持してはなりません。また、イベントのハイドレーションは、データを永続化する場合にのみ発生します。読み取り側では、通常は階層型システムで発生するエンティティ-> DTO-> ViewModel変換がなく、フル機能のORMが通常行うようなオブジェクトの変更追跡はありません。ほとんどのシステムは、書き込みよりもはるかに多くの読み取りを実行します。

  4. さまざまなデータコンテキストの初期化が原因で複数の異種データベースを使用している場合、起動時間が長くなると若干の問題が発生する可能性があります。ただし、ADO .NETのような単純なものを使用して、イベントストアと読み取り側のマイクロORMを操作する場合、システムは、フル機能のORMよりも「コールドスタート」が速くなります。 。ここで重要なことは、データへのアクセス方法を過度に複雑にすることではありません。これは、実際にはCQRSが解決するはずの問題です。そして、前に述べたように、読み取り側はビュー用にモデル化し、再オーバーヘッドのないようにする必要があります。 -データのマッピング。

  5. 私の経験では、2フェーズコミットは、何千人ものユーザーのために拡張する必要がないシステムに適しています。分散トランザクションコーディネーターと適切に連携するデータベースを選択する必要があります。 PostgreSQLは、たとえば、個別のモデルの読み取りと書き込みに適しています。多数の同時ユーザーに合わせてシステムを拡張する必要がある場合は、結果の一貫性を考慮して設計する必要があります。最終的な整合性を回避するためにCQRSを使用しない集約ルートまたはコンテキスト境界が存在する場合があります。ドメインの非共同作業部分には意味があります。

  6. イベントストアに適切なデータベースを選択すると、JSONやXMLなどのシリアル化された形式でイベントをクエリできます。そして、それは分析の目的でのみ行われるべきです。システム内部では、ルートIDの集約とイベントタイプ以外の方法でイベントストアをクエリすることはできません。そのデータはインデックスに登録され、シリアル化されたイベントの外部に存在します。

32
Dmitry S.

ポイント5についてコメントするだけです。FacebookはESを結果整合性で使用すると言われています。そのため、投稿後に投稿が消えて再表示されることがあります。

通常、ブラウザがアクセスしている読み取りモデルは「近い」場所にありますが、投稿を行うと、SPAは書き込みモデルに近い読み取りモデルに切り替わります。書き込みモデル(イベント)と読み取りモデルが近接しているため、自分の投稿を見ることができます。

ただし、15分後、SPAは最初のより近い読み取りモデルに戻ります。投稿を含むイベントがその読み取りモデルにまだ伝達されていない場合は、自分の投稿が消えてしばらくしてから再び表示されます。

7
Sam Stickland

この質問が寄せられてからほぼ3年になりますが、それでも この記事 は誰かにとって役立つかもしれません。要点は

  • スナップショットを使用したスケーリング
  • データの可視性
  • スキーマの変更
  • 複雑なドメインを扱う
  • ほとんどの新しいチームメンバーに説明する必要がある
1
kagetoki

返事をするのに遅れないようにしたいです。ここ数か月の間、ESが理にかなった私のアーキテクチャの一部にprduction-gradeソリューションを実装することを目的として、その議論について多くの研究を行いました

複雑:実際には、複雑であってはなりません。その使命は、非常に単純であることです。どうやって?ビジネスロジックコードからインフラストラクチャコードにすべての複雑さを押し込みます。データアクセスは、まだ十分に成熟していないフレームワークで行う必要があります。それでもニッチ/ヒップスターアプローチ(?)であるため、ES/CQRSレースでの明確な勝者はまだありません

ディスク領域の使用率が高い:もっと言う、*潜在的に無限*のディスク使用率。しかし、ESに移行する場合、この明らかなdrwabackを許容する十分な理由もあります。それらのいくつかをあげましょう:

  1. 監査ログ:データストアはイベントログであり、すでにわかっています。金融アプリまたはすべてのミッション/セーフティクリティカルには、Whoを作成したことを示すWhatinWhich moment。 ESはこのボックスの機能を提供します...ビジネスに意味のあるメタデータでイベントエントリを装飾することもできます(たとえば、トランザクションIDとAPIコンシューマーIDの相関、操作の重大度レベル...)

  2. High Concurrency:論理リソースの状態が多数のクライアントによって同時に変更されるシステムがあります。これらはゲーム、IoTプラットフォームなどです。状態表現を変更する代わりにイベントをログに記録することは、イベントの全体的な順序を提供するための賢明な方法になる可能性があります。もう1つの方法は、同期化に関するものをDBに委任することです。しかし、ESに興味があるなら、これはあなたが望むものではありません。

  3. Analytics大量のビジネス価値を持つ大量のデータがあるとしましょう。長年にわたり、データ構成をさまざまな情報モデル(OLAPキューブ)に変換することにより、アプリケーション情報から知識を抽出しました。イベントストアは、箱から出してすぐに同様のものを提供します。イベントログは、情報を表す最も粗い形式です。また、保存したイベントにバッチで、または反応して、さまざまな方法でそれらを処理できます。

メモリ使用量が多い:プロジェクションを構築したら、同じになると思います

起動時間が長い:読み取り側がその予測をキャッシュし、最後の更新イベントを「記憶」している場合、イベントシーケンス全体を再適用しないでください。スナップショットは軽減策ですが、多くのスナップショットを作成する場合、ESで不適切な選択をした可能性があります。この問題は、サービスを中断することなく起動時間をマスクできるマイクロサービスエコシステムでは軽微だと思います。実際、マイクロサービスを適用すると、ES/CQRSを最大限に活用できます

結果整合性:ESではなく、CAPの定理を非難します。多くの非ES/CQRSはこれに対処する必要がありますが、それが実際の問題ではないシナリオがたくさんあります。これらは、ESがうまく適合するシナリオです。また、ESサービスと非ESサービスを同じプラットフォームに混在させることができます

イベントストア内のシリアル化されたイベント:シリアル化されていないイベント表現を持つことが重要な場合は、ドキュメント指向のDBを使用できますが、これを実行してイベントのペイロードに対してクエリを実行すると、要点が失われますES/CQRSの。 ESとは、すべてのデータ操作をDB側からアプリケーション層に移動することを意味します。アプリケーション層では、すべての部分が急速に変化し、すべてが無統計です。これにより、スケーラビリティとフォールトトレランスが強化され、チームの編成を形作る手段が提供されます。フロントエンドの男/女にBFFをJavaScriptで簡単に記述させるなどの操作を実行できます。

私はこの原則を実践して良い結果をもたらし、このエキサイティングなアプローチのメリットを活用したいと思います

1
Carmine Ingaldi

イベントソーシングとCQRSはすばらしいものです。大きなデータの移行プロジェクトがない限り、開発者がアプリケーションの存続期間中に作業しなければならない1つの事前にモデル化されたデータベースで開発者を悩ませることがなくなるためです。

これは大きな誤解です。リレーショナルデータベースは、モデルの進化のために発明されました(定義済みの階層構造とは対照的に、単純な2次元テーブルのおかげです)。データアクセスのカプセル化を保証するビューと手順により、論理モデルと物理モデルは独立して進化できます。これが、SQLがDDLとDMLを同じ言語で定義する理由でもあります。一部のRDBMSでは、それらすべての進化をOracle Edition Based Redefinitionとしてオンラインでバージョン付けおよび展開(継続的デリバリー)することもできます。

ビッグデータ構造は事前定義されており、この構造用に開発されたコードでのみ読み取ることができます。 Okすぐに消費すると、正確なバージョンと言語コンパイラまたはインタープリタがないと、10年後にそれを読むのが困難になります。

1
FranckPachot