5

MySQLクラスターのような分散サーバーを使用して、複数のサーバーに展開されているasp.netWebアプリケーションで「ロック」を実行できる方法があるかどうかを知りたいです。

たとえば、アカウントの残高を更新する典型的な例を考えてみましょう。2つのリクエストで同じアカウント残高を同時に更新することはできません。例えば:

メンバー1の口座残高は100です。

  • リクエストAはサーバー1にアクセスして、メンバー1の残高に100を追加します
  • リクエストBはサーバー2にアクセスして、メンバー1の残高に50を追加します

したがって、リクエストAは残高を100から200に更新し、保存します。
リクエストBは残高を150に更新し、保存します。

これらはすべてまったく同時に発生するため、最終結果は250になるはずなので、情報が失われます。

リクエストBが残高を取得するまでリクエストAが終了するまで待機する必要があるように、どのようにロックできますか。単一のプロセスの場合、これはアプリケーション全体のロックによって実装できます。ただし、複数の独立したプロセスがあるため、これはサーバー1の場合は機能せず、ロックされておらず、サーバー2も機能しません。

これをどのように行うことができるかについてのアイデアやベストプラクティスはありますか?

4

3 に答える 3

4

それがトランザクションの目的です。

アトミックにする必要がある操作を にラップしTransactionScopeて、明示的なトランザクションに登録します。

これは、古いデータの問題を完全に解決するものではありません。トランザクションが完了すると、他の同時ユーザーが古い値を使用して更新している場合でも問題が残るからです。

解決策は、行が変更されるたびに変更されるテーブルのフィールドを使用することです。SQL Server 2008 では、これはrowversionタイプです。

が変更されていない場合にのみ行を更新しますrowversion。変更されている場合は、ユーザーに通知し、更新を行わずに現在の値を戻します。

于 2011-12-21T14:08:23.840 に答える
1

私が作成した ORM では、ロック機構を実装しました。Product、Customer などのエンティティの各タイプには、「LockedBy (int)」と「LockedAt (datetime)」の 2 つの追加フィールドがあります。

LockedBy にはエンティティをロックしたユーザーの ID が含まれ、lockedAt にはエンティティがロックされたときのタイムスタンプが含まれます。

したがって、ユーザーがエンティティの編集を開始したい場合、コードは次のプロセスを実行します。

DB からエンティティを取得します。'1' は ProductID です

Product p = new Product(1);

エンティティを現在ログインしているユーザーにロックします

entity.Lock();

エンティティをデータベースに保存/コミットします。Save() は LockCheck() を呼び出します。これは、ログインしているユーザーがエンティティを保存する権限を持っている場合に true を返します。

entity.Save();

次の場合、ユーザーにはエンティティを保存する権限があります。

 (LockedBy < 0 || LockedBy == LoggedInUser.UserID || LockedAt < DateTime.Now.AddMinutes(-30))

注: ユーザーは、30 分以上前にロックされたエンティティを編集できます。別のユーザーが (編集画面で) エンティティを開いている場合、15 分ごとにポップアップして、ユーザーがまだそこにいるかどうかを尋ねます。

この時点で、他のユーザーはこのエンティティを編集できません!

コード/ユーザーは、このエンティティを好きなだけ自由に編集でき、元に戻った後に変更されていないことを確認できます:)

ユーザーがコード呼び出しの編集をやめたら:

entity.Unlock()

それから

entity.Save()

これにより、他のユーザーが編集できるようにエンティティが解放されます

于 2012-06-27T16:45:32.877 に答える
1

ここで、 Redis の pub/sub メカニズムのようなシステムが役に立ちます。基本的には、サブスクライバー (他の負荷分散サーバー) にメッセージを送信して、イベントが発生したことを知らせる方法です。ServiceStack Redis クライアントはこれを完全にサポートしています。

于 2013-03-07T15:54:11.290 に答える