2016-10-22 62 views
0

我有一個web api處理來自不同渠道的支付(並管理用戶賬戶)。我面臨的問題是,如果同一用戶正在從不同的渠道進行交易 - 帳戶餘額就會折騰。同步任務處理僅針對同一用戶

例如考慮這種情況下發生的所有在一秒鐘內具有重疊的執行時間:

  • R1 - USER1撤回100
  • R2 - 用戶2撤回10
  • R3 - 用戶1撤回50
  • R4 - User3退出20
  • R5 - 用戶2退出100
  • R6 - 用戶4退出20

那是因爲所有帳戶都在同一時間處理,並帶來災難性結果。我介紹了線程鎖定(鎖定& Monitor/TryEnter),但這意味着所有請求都會放在一個隊列中。即使用戶4與其他用戶沒有任何關係,也必須等待所有其他請求完成。

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 &用戶2請求單獨的隊列和休息,同時進行處理。

理想排隊

  • R1,R3
  • R2,R5
  • R3
  • R4

如何實現這一目標?

歡呼

+0

對於誰來到這裏有類似的問題 - SP是有點嚴重編碼,而不是鎖定SELECT和UPDATE記錄。我修復了事務並且事情正在進行中 – sabkaraja

回答

3

鎖定在的WebAPI代碼級別訪問該帳戶是絕對錯誤的方式。面對惡意請求,您會殺死性能並使您的系統無法使用。更糟糕的是,由於不可預測的線程池回收,這絕對不可靠(例如,在使用IIS的情況下)。

您需要的是在數據庫級別使用事務。交易開始並鎖定帳戶後,應檢查餘額並在此之後進行適當的更改。

+0

我已經在db中的rowlevel上實現了rowlock,updlock,但不知何故它完全沒有達到目的。 BEGIN TRANSACTION trans UPDATE PlayerBalance WITH(UPDLOCK,ROWLOCK)SET availableBalance = @ClosingBal WHERE ID = @ PID COMMIT TRANSACTION trans 但它似乎不起作用。在50-100毫秒之內的事務也發佈重疊的請求。這就是爲什麼我使用代碼進行線程化的原因。 我不知道如果我做錯了。 – sabkaraja

+0

根據您的應用程序的體系結構,您有幾種正確實現事務的方法。關鍵時刻是鎖定你真正必須鎖定的東西。沒有看到代碼,對於SQL Server,我可以建議查看sp_lock存儲過程MSDN文檔。 – olk

+0

我犯了一個錯誤,不是sp_lock,而是sp_getapplock和sp_releaseapplock。 :) – olk