4

以前に WCF サービスを使用したことがありますが、現在は新しいプロジェクトが予定されています。私はまだ設計段階にあり、次のシナリオを処理する最善の方法を考えました。

複数のクライアントが同時に WCF サービスに接続し、サービスでさまざまなメソッド (操作コントラクト) を起動します。

A.実行されるメソッドの一部は、純粋な「読み取り」メソッドです (GetListOfCustomers など)。

B.実行されるメソッドには、複雑な「読み取り」メソッド (GetAllProductsByCustomerId など) があります。この種の方法では、DB から顧客を取得し、顧客について何かをチェックしてから、顧客が購入したすべての製品を取得する必要があります。(つまり、このメソッドではデータベースへの呼び出しが 2 回あります)。

C.一部は「書き込み」メソッドです (例:「RemoveCustomer」または「SetProductOutOfStock」)。

私の質問は、同時実行の問題が発生しないように、これらすべての呼び出しを同期するにはどうすればよいですか?

クライアント側のパフォーマンスが低下するため、サービス全体で呼び出しを連続して処理したくありません (一部の呼び出しでは、処理に 3 ~ 4 秒かかる場合があります) だから私の解決策は何ですか?

「複数」スレッドを持つすべてのクライアントに「単一」インスタンスを使用してから、ロック オブジェクトを使用しますか? これは単にシリアルになるだけではありませんか?

または、「読み取り」用に別のロック オブジェクトが必要で、「書き込み」用に別のロック オブジェクトが必要ですか?

または、「書き込み」機能にはロックが必要で、「読み取り」機能には他のものが必要ですか?

これは、StackOverflow に関する私の最初の質問です。助けてくれてありがとう!

更新: ORM として「Linq-To-SQL」を使用します。

4

4 に答える 4

2

データの一貫性の問題や、データベース クエリを実行する際の同時実行性について心配する必要はありません。私があなたの状況を正しく理解していれば、「アトミック」にしたい一連のデータベースクエリを実行している間、トランザクションを一貫して使用することだけを確認する必要があります。私は例でそれを説明しようとします:

  1. データベースからすべての顧客を取得します。
  2. 顧客ごとに、いくつかの関連データを更新するクエリを実行します。

このシナリオで発生したくないのは、クエリからの戻り、からのすべてのクエリが終了する前に、別のクエリによってデータが変更される状況に陥ることです。たとえば、その間に顧客の 1 人が削除された場合、関連するデータを更新しても意味がなく、エラーが発生する可能性さえあります。12

だからあなたがする必要があるのは、BEGIN TRANSACTIONbefore1COMMITafterのようなものを置くこと2です。使用している SQL ダイアレクトの正確な構文を調べてください。

これにより、基本的に、使用しているデータが変更されないことが保証されます。実際、トランザクションによってロックされます。同じデータで機能する可能性のある他のすべてのクエリは、トランザクションが完了するのを待っています。データベースはこの種のロックをインテリジェントに行い、常にできるだけ少ないデータをロックしようとします。

于 2012-04-15T22:39:06.107 に答える
0

CQRSについて何か読むことをお勧めします。これは、直面している課題に対処するためのアーキテクチャ パターンです。

状況の解決策の例として、次の図は、要件を満たすことができる CQRS アーキテクチャです。

ここに画像の説明を入力

さらに説明が必要な場合は、喜んで提供します。

アップデート

主な原則は、データベースの読み取りと書き込みを異なるデータベースに分離することです。

次に、レプリケーションを使用して、読み取りデータベースが最新であることを確認します。

両方のデータベースを 1 つに結合し、両方のサービスを 1 つに結合することによって、上記のアーキテクチャを実現することもできます。ただし、最初の質問は、競合するデータベースの使用パターンがあるという事実に基づくデータベースの競合に関するものでした。

これが、解決策として CQRS を提案した理由です。データベースの書き込み側は読み取り側から分離されています。読み取り側は、選択用に最適化できます (アクセス速度のために非正規化することもできます)。

これは、同じインターフェイスを介して読み取り操作と書き込み操作の両方を実行している場合と同じ競合の問題に直面しないことを意味します - これが現在のアプローチです。

さらに、サービスを介して読み取り操作を公開する必要はありません。単純な ADO で十分であり、サービス エンドポイントによってレイテンシが発生するだけです。

読み取りモデルから読み取るとき、および db 書き込みサービスがデータ モデルを更新するときも、引き続き linq2sql を使用できます。

于 2012-04-16T07:37:44.993 に答える
0

Web 向けに設計しているため、同時実行性を採用する必要があります。解決策はありません。私の意見では、ロックを取得してすべてを Web で作業するのは良い方法ではありません。同時アクセスが発生するため、同時実行の問題を防ぐのではなく、同時実行エラーに対処する方法を考える必要があります。Web 上に構築された同時実行制御メカニズムは、用途が限定されており、正しく構築するのが困難です。

于 2012-04-16T07:26:37.140 に答える
0

私の質問は、同時実行の問題が発生しないように、これらすべての呼び出しを同期するにはどうすればよいですか?

なぜ何かを同期する必要があるのでしょうか? DBMS は同期を非常にうまく処理できます。もちろん、ロックが原因で読み取りパフォーマンスが低下する大量の書き込みが発生することがわかっている場合は、アーキテクチャ レベルでそれを計画する必要がありますが、WCF とはあまり関係ありません。その場合、hugh が書いたように、CQRSは適切な選択かもしれませんが、手元にある仕様なしでは言いにくいです。

クライアント側のパフォーマンスが低下するため、サービス全体で呼び出しを連続して処理したくありません (一部の呼び出しでは、処理に 3 ~ 4 秒かかる場合があります)。だから私の解決策は何ですか?

次に、PerCall インスタンス化と、可能であれば単一または複数の同時実行を使用します。インスタンス化と同時実行の組み合わせの詳細については、こちらをご覧ください。

「複数」スレッドを持つすべてのクライアントに「単一」インスタンスを使用してから、ロック オブジェクトを使用しますか? これは単にシリアルになるだけではありませんか?

単一のインスタンス化では、同時実行の問題が発生します。上記でリンクした記事を参照してください。シングルトン サービスが必要な場合に最も役立ちます。


アップデート

あなたのコメントへの回答: 残念ながら、並行性の問題が発生する可能性がある場所をまだ理解していません。WCF サービスについて心配している場合は、Single インスタンスの使用を避けてください。最もスケーラブルなオプションは PerCall/Multiple です。

CQRS を検討する必要があるかどうか自問自答している場合は、別のコメントでリンクした Udi Dahan の記事を自由に読んでください。ただし、CQRS は理解するのに時間がかかり、必要な場合とそうでない場合があるプロジェクトが複雑になることに注意してください。

アーキテクチャを無用に過度に複雑にしないことをお勧めします。私には、サービスのインスタンス化/同時実行の適切な構成で十分であるように思えます。確信が持てない場合は、システムの予想される負荷を偽るプロトタイプを作成してください。特に長寿命のアプリケーションになる場合は、申し訳ありませんが、より安全です。

于 2012-04-16T08:24:32.570 に答える