web-dev-qa-db-ja.com

リポジトリー・パターンを使用するときに並行性の問題を防ぐにはどうすればよいですか?

それを考慮して:

  • エンティティを扱うリポジトリパターンを使用する場合-エンティティは(Hibernateに関係なく、または「手動で」)永続化するアトミックユニットです
  • エンティティを変更する場合、エンティティ全体を保存します(セットまたはインクリメントフィールドはありません)
  • 複数のアプリケーションインスタンスが実行されている可能性があります
  • 同じエンティティが異なるアプリケーションインスタンスによって同時にフェッチ/変更/保存される可能性があります

これは結局不良データにつながりませんか? 「ユーザーエンティティでのパスワードの再試行回数を節約させて」の使用例を考えてみましょう。攻撃者がログインするために多数の複数のクライアント要求を実行した場合、それは問題になりませんか?インスタンスAがエンティティをフェッチし、インスタンスBが同じエンティティをフェッチし、インスタンスAがそれを変更/保存し、インスタンスBがAの変更/保存に気づかずに元のエンティティを変更/保存します。

7
Luís Soares

リポジトリパターン は、同時実行性の問題を解決することを意図していません。永続エンティティを操作する便利な方法を提供するだけです。

原則として、次のものと組み合わせてリポジトリパターンを使用します。

  • 作業単位 :データベース内で一貫して更新する必要がある変更されたオブジェクトを追跡し、潜在的な同時実行の問題が発生した場合にそれを管理します。
  • IDマップ :これにより、同じクライアントセッションで同じエンティティが異なるオブジェクトにロードされなくなり、不整合が発生する可能性があります。
  • 並行性パターン:これらは、複数のクライアントまたはサービスが関与する場合の一貫性を管理します。

また、同時実行パターンは複雑なトピックです。マーティンファウラーは、優れた著書 Patterns of Enterprise Architecture で、たとえば次の代替案を示しています。

  • 楽観的ロック :データを書き込む必要があるときにロックを取得し、すべてがうまくいくことを期待します。
  • 悲観的ロック :データが変更される前に排他的アクセスを取得しようとします。

ただし、さまざまなデータベースにさまざまなサービスのデータがあるマイクロサービスアーキテクチャでは、より創造的な代替手段を使用します。たとえば、Chris Richardsonは、彼の優れた Microservices Patternssaga pattern を提案します:ロックする代わりに2フェーズコミットスキームのデータでは、ステータス管理でdo/undoロジックに従うステップのオーケストレーションを使用します。

6
Christophe