簡體   English   中英

SQL Server,使用表作為隊列

[英]SQL Server, using a table as a queue

我使用SQL Server 2008 R2作為排隊機制。 我將項添加到表中,外部服務讀取並處理這些項。 這很好用,但缺少一件事 - 我需要機制,我可以嘗試從表中選擇一行,如果沒有,則阻塞直到有(優選在特定的時間段內)。

任何人都可以建議我如何實現這一目標?

實現非池阻塞隊列的唯一方法是WAITFOR (RECEIVE) 這意味着Service Broker隊列具有所有增加的開銷。

如果您使用普通表作為隊列 ,則無法實現非輪詢阻止。 您必須通過請求出列操作來輪詢隊列,如果它沒有返回任何內容,請休眠並稍后再試。

我擔心我會在這里不同意Andomar:雖然他的答案是一個普遍的問題,但桌子上有沒有排? 當涉及到排隊時,由於重疊入隊/出隊的繁忙性質,檢查這樣的行是一個(幾乎)保證在負載下的死鎖。 當使用表作為隊列時,必須始終堅持基本的入隊/出隊操作,不要嘗試花哨的東西。

“自SQL Server 2005引入OUTPUT子句以來,使用表作為隊列不再是一個難題”。 關於如何做到這一點的好文章。

http://rusanu.com/2010/03/26/using-tables-as-queues/

我需要一種機制,我可以嘗試從表中選擇一行,如果沒有,則阻塞直到有(優選在特定的時間段內)。

您可以每秒循環並檢查新行:

while not exists (select * from QueueTable)
    begin
    wait for delay '00:01'
    end

免責聲明:這不是我將用於生產系統的代碼,但它可以滿足您的要求。

之前提出使用Service Broker的評論者可能得到了最好的答案。 Service Broker允許您在等待更多輸入時實質上阻止。

如果Service Broker過度,您應該考慮采用不同的方法解決問題。 你能提供你想要做的更多細節嗎?

讓我分享一下我在這方面的經歷,你會發現它很有幫助。

我的團隊首先使用MSMQ事務隊列來提供我們的異步服務(無論是IIS托管還是WAS)。 我們遇到的最大問題是重負載下的MS DTC問題,例如100多條消息/秒負載; 所有這一切都是一個緩慢的數據庫操作,開始導致超時異常和MS DTC會讓房子倒閉(如果事情變得很糟糕,交易實際上會丟失),雖然我們不是100%確定根直到今天,我們懷疑群集環境中的MS DTC存在一些嚴重問題。

因此,我們開始研究不同的解決方案。 Windows Server的Service Bus(Azure Service Bus的內部部署版本)看起來很有前途,但它是非事務性的,因此不符合我們的要求。

由於我們的事務要求,我們最終決定采用自己動手的方法,這是由構建Azure Service Bus的人員向我們建議的方法。 從本質上講,我們遵循Azure Worker Role模型來獲取將通過某個隊列提供的輔助角色; 一個輪詢阻止模型。

老實說,這對我們來說比我們使用過的任何東西都要好得多。 這種服務的偽代碼是:

hasMsg = true

while(true)

    if(!hasMsg)
         sleep

    msg = GetNextMessage

    if(msg == null)
        hasMsg = false
    else
        hasMsg = true

    Process(msg);

我們發現這種方式的CPU使用率明顯較低(低於傳統的WCF服務)。

當然,棘手的部分是處理交易。 如果您希望從隊列中讀取多個服務實例,則需要在sql中使用read-past / updlock,並且還要讓.net服務以一種滾動的方式登記到事務中。如果服務失敗了。 在這種情況下,除了常規隊列之外,您還需要將重試/毒葯隊列作為表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM