2016-10-22 6 views
0

私は、異なるチャネルからの支払いを処理(およびユーザーアカウントを管理)するWeb APIを持っています。私が直面している問題は、同じユーザーが異なるチャネルから取引している場合 - 口座&残高がトスになることです。同じユーザーのみの同期タスク処理

例えば、このシナリオは、すべての実行時間をオーバーラップして1秒で何が起こって考えてみます。

  • R1 - 100
  • R2を撤回USER1 - 10
  • R3を撤回USER2 - 50
  • R4を撤回USER1 - User3 withdraw 20
  • R5 - User2 withdraw 100
  • R6 - User4 withdraw 20

すべてのアカウントが同時に処理され、悲惨な結果に終わったためです。スレッドロック(ロック& Monitor/TryEnter)を導入しましたが、それはすべてのリクエストが1つのキューに入ることを意味します。 User4が他人と何もしていない場合でも、他のすべてのリクエストが完了するまで待たなければなりませんでした。

public class PaymentProcessor 
{ 
    private static object _lockobject = new object(); 
    public void process() { 
     if (Monitor.TryEnter(_lockobject, TimeSpan.FromSeconds(5))) 
     { 
      ProcessRequest(xmlData); //ignore xmlData 
      Monitor.Exit(_lockobject); 
     } 
    } 
} 

理想的には、私は、ユーザー1 & User2の要求のための別々のキューが好きで、同時に処理することが休むでしょう。

理想的には、キュー

  • R1、R3
  • R2、R5
  • R3
  • R4

どのように私はこれを達成できますか? WEBAPIコードのレベルでのアカウントへのアクセスをロック

歓声

+0

同様の問題を抱えているのは誰ですか?SPは重大なコードであり、SELECTとUPDATEのレコードをロックしていません。私はトランザクションを修正しています。現在は動作しています – sabkaraja

答えて

3

は絶対に間違った方法です。あなたは悪意のある要求に直面してパフォーマンスを殺し、システムを無防備にします。さらに悪いことに、これは予測不能なスレッドプールリサイクルのために絶対に信頼できません(たとえば、IIS使用の場合)。

必要なのは、データベースのレベルでのトランザクションの使用です。トランザクションが開始され、アカウントがロックされた後、残高をチェックしてから、適切な変更を行うことができます。

+0

私はdbでrowlevelでrowlock、updlockを実装しましたが、何とか目的を果たしていません。 ID = @ PID が トランストランザクションのコミットしかし、動作するように見えるdoes notのTRANSACTIONトランス UPDATE PlayerBalance WITH(UPDLOCK、ROWLOCK)SET availableBalance = @ ClosingBalを開始します。 50〜100ミリ秒以内に発生するトランザクションも、重複する要求をポストします。それで私はなぜコードのスレッド化に頼ったのですか? 私が間違ったやり方をしているかどうかはわかりません。 – sabkaraja

+0

アプリケーションのアーキテクチャに応じて、トランザクションを正しく実装する方法はいくつかあります。重要なのは、本当にロックしなければならないものをロックすることです。コードを見ることなく、SQL Serverでは、sp_lockストアドプロシージャのMSDNドキュメントを参照することをお勧めします。 – olk

+0

私はsp_lockではなくsp_getapplockとsp_releaseapplockを間違えました。 :) – olk

関連する問題