2011-12-29 87 views
2

我開始之前,我無法找到任何其他資源來回答我的問題,最接近的是:
Calling a stored procedure simultaniously from multiple threads in asp.net and sql server 2005
但它沒有回答我的具體問題/關注。多asp.net請求調用相同的SQL Server 2005存儲過程

基本上,我有一個龐大的.NET網絡應用程序,每天處理數百萬個請求。

假設:

  • 所有有關存儲過程是簡單的GET存儲過程(例如,選擇[SOMETHING] FROM [某處] INNER JOIN [別的]等....)
  • 所有數據永遠不會改變(它會不時變化,爲了我的情況,假設它不會)
  • 無論什麼原因,緩存最初都是空的。

問題的方法:
我檢查應用程序緩存中的對象的存在。如果存在,我只需返回它。如果對象不在高速緩存中,則會對數據庫執行臨時調用以查找此數據。一旦該sproc返回,該數據將被添加到緩存中,然後返回。

重負載下我有一點性能問題,我想清除。

這裏是我的情況:

  1. 用戶A進入此方法。
  2. 數據不在緩存中,sproc被調用。
  3. 用戶B進入此方法(雖然sproc仍在運行)。
  4. 數據不在緩存中,sproc被調用。
  5. 沖洗並反覆重複。

在重負載下,這些可能會產生相當多的併發和冗餘活動spid。我試圖找出解決這個問題的最佳方法。很明顯,我可以放入一個sp_getAppLock,但這些請求仍然會結束1)放入sproc,2)必須觸發完全相同的查詢。我可以鎖定特定於該確切查詢的對象,並將其包裝在緩存檢查中。但是如果我這樣做,我可能會爲一些大規模的線程爭奪和僵局而打開大門。

我不得不假設有人已經處理過這種情況,我希望有一個合適的解決方案。現在我可以提出的最佳解決方案是應用程序鎖定,但我真的很想知道任何人是否有更好的選擇。也許是組合的東西,比如SQL應用程序鎖定和消息傳遞(傳統或非傳統),在鎖定成功之後,剛剛發佈的任何剛剛發佈的嘗試將結果集(從何處?)拉下來,而不是重新執行整個其餘部分。

編輯:
所以按照這個....如果我鎖定或「等待」無論是緩存或存儲過程的調用,重負載下有可能,如果一個元素沒有被緩存,而該方法(或存儲過程)生成要緩存的對象可能最終花費比預期更長的時間。雖然這是旋轉,線程將不得不等待。通過等待,唯一的方法(至少我知道)是鎖定或旋轉。

難道不可能讓線程池耗盡或鎖定所有可用請求並強制請求排隊?這是我的恐懼和驅使我去考慮將應用程序層移動到數據庫中的事情。上次我們嘗試鎖定緩存時,我們的網絡盒遭受了嚴重的CPU峯值,因爲這些線程長時間處於鎖定狀態。雖然我相信當時我們沒有使用Monitor.Enter/Monitor.Exit(或者只是鎖定(){})。無論哪種方式,任何人都沒有在這方面的任何細節或經驗?出於這個原因,我知道鎖定長時間運行的進程通常是不好的形式。如果我可以避免阻止用戶請求放入請求隊列,因爲我全部脫離線程或所有活動請求都被鎖定,我會忍受將重複內容加載到緩存中。

或者,也許這只是晚了,我在想這個。我以一個幾乎燦爛的「啊哈」時刻開始了我的一天。但現在我只是繼續猜測自己。

+0

這是一個ASP.NET問題,而不是T-SQL。數據庫服務器如何知道你爲什麼稱它? – gbn 2011-12-29 18:28:41

+0

這是一個多線程/資源爭用問題。它不是C#,不是asp.net,而不是sql。 – 2011-12-29 18:39:03

+0

確實如此。雖然這是一個多線程/資源爭用問題,恰好處理所有這些元素。那裏是我使用這些標籤的原因。 – John 2011-12-29 18:47:19

回答

2

您的緩存很可能受鎖的保護,因此您已經序列化線程。

您建議的解決方案是最好的:鎖定查詢。一旦緩存填充後,性能差異將可以忽略不計,並且您將避免多個(並且昂貴的)數據庫查詢。

0

在過去,我有這個問題,當緩存被刷新和緩慢的查詢把我的數據庫關閉。

這裏是一些解決方案,這個沉重的問題是使用鎖定,忽視了希伯來文解釋,並查找代碼:

http://blogs.microsoft.co.il/blogs/moshel/archive/2009/07/11/cache.aspx

+0

這個例子顯示了我是否應該鎖定字符串的任何建議?不知道我是否應該擔心實習,但說我有這個應用程序的多個實例運行。不是實習生表明我可能會鎖定跨域嗎?原諒我的無知。 – John 2011-12-29 18:39:21

+0

由於我使用Cache()(或Memcache),我需要使用這些字符串,並知道我在做什麼。 您可以使用鎖定對象,或者使用'Monitor.TryEnter()'獲取/設置鎖定超時。 – 2011-12-29 18:59:41

0

你可能想看看緩存優化,如果你還沒有這樣做的話。

0

如果你正在通過緩存管理器運行,它是否能夠足夠聰明地知道proc已經被調用並且應該等待它完成?

GetData() { 
    if (cached) return cache; 
    if (caching) { 
    // wait for it to finish 
    return cache; 
    } 
    caching=true; 
    cache = CallProc(); 
    cached = true; 
    caching = false; 
} 
+0

我們之前已經嘗試過這種方式,但運行速度慢的sprocs最終導致嚴重的請求鎖定/排隊。我想我們可以再試一次。我確信我可以在這個級別上寫點東西來忽略這些,或者做一些更智能的事情。無論哪種方式,我認爲這是我必須遵循的方向,非常感謝。 – John 2011-12-29 18:44:53