簡體   English   中英

如何在WCF服務中同步數據庫訪問?

[英]How to synchronize database access in a WCF Service?

以前我曾經使用過WCF服務,現在我有一個新項目即將來臨。 我仍處於設計階段,我想知道處理以下情況的最佳方法是什么。

我將有多個客戶端同時連接到WCF服務,並在該服務上觸發不同的方法(運營合同):

答:某些燒制的方法只是單純的“讀”方法(如GetListOfCustomers)。

B.觸發的一些方法是復雜的“讀取”方法(例如,GetAllProductsByCustomerId)。 這些方法需要從數據庫中獲取客戶,檢查客戶的東西,然后獲取客戶購買的所有產品。 (意味着,此方法有2次對數據庫的調用)。

C.有些是“寫”方法(例如,“ RemoveCustomer”或“ SetProductOutOfStock”)。

我的問題是-如何同步所有這些調用,以免出現並發問題?

希望整個服務都按順序處理呼叫,因為這會損害客戶端的性能(某些呼叫可能需要3-4秒來處理)。 那么我的解決方案是什么?

對具有“多個”線程的所有客戶端使用“單個”實例,然后使用鎖定對象? 這不是序列化的結果嗎?

還是我需要為“讀取”使用不同的鎖定對象,為“寫入”使用不同的鎖定對象?

還是我需要為“寫”功能加鎖,為“讀”功能加一些鎖?

這是我有關StackOverflow的第一個問題。 感謝任何可以提供幫助的人!

更新:我將使用“ Linq-To-SQL”作為我的ORM。

您既不必擔心數據一致性問題,也不必擔心執行數據庫查詢時的並發性。 如果我正確理解了您的情況,那么您需要確保的是,在執行一系列您希望是“原子的”數據庫查詢時,您始終使用事務。 我將嘗試通過一個示例進行解釋:

  1. 從數據庫中獲取所有客戶。
  2. 對於每個客戶,執行查詢以更新一些相關數據。

你不希望在這種情況下會發生什么是進入的情況下,當數據被另一個查詢的查詢之后更改從1的回報,並從所有查詢之前 2完成。 例如,如果同時刪除一位客戶,則更新相關數據毫無意義-甚至可能導致某些錯誤。

因此,您需要做的就是將BEGIN TRANSACTION放在1之前,並將COMMIT放在2之后。 查找您使用的SQL方言的確切語法。

基本上,這將確保您使用的數據不會更改。 實際上,它將被您的交易鎖定; 而其他所有可能使用相同數據的查詢都在等待您的交易完成。 數據庫會智能地進行這種鎖定,始終嘗試鎖定盡可能少的數據。

您正在為Web設計,因此您需要擁抱並發,沒有出路。 在我看來,鎖住所有東西並不是在Web上工作的好方法。 並發訪問將會發生,您需要考慮如何處理並發錯誤,而不是防止並發問題。 在Web上構建的任何並發控制機制使用受限,並且難以正確構建。

我建議您閱讀有關CQRS的內容 ,這是一種體系結構模式,可以某種方式解決您面臨的挑戰。

作為針對您的情況的示例解決方案,下圖是可以滿足您的要求的CQRS體系結構。

在此處輸入圖片說明

如果您想進一步說明,我們將很樂意提供。

更新

主要原理是您將數據庫讀取和寫入操作分離到不同的數據庫中。

然后,使用復制來確保讀取的數據庫是最新的。

您還可以通過將兩個數據庫合並為一個,並將兩個服務合並為一個,來實現上述架構。 但是,您最初的問題是關於數據庫爭用的,因為您的數據庫使用模式存在沖突。

因此,這就是為什么我提議使用CQRS作為解決方案的原因-數據庫的寫側與讀側分離。 讀取側可以針對選擇進行優化(甚至可以針對訪問速度進行反規范化)。

這意味着您將不會像通過同一接口同時執行讀寫操作那樣面臨相同的爭用問題-這是您當前的方法。

另外,您不需要通過服務公開讀取操作-簡單的ADO可以很好地完成服務,而服務端點僅會引入延遲。

從讀取模型讀取數據時,以及在數據庫寫入服務更新數據模型時,仍可以使用linq2sql。

我的問題是-如何同步所有這些調用,以免出現並發問題?

為什么需要同步任何內容? DBMS可以很好地處理同步。 當然,如果您知道由於鎖定將有大量寫入操作會降低讀取性能,那么您將不得不在體系結構級別上進行規划,但這與WCF無關。 正如休所寫的那樣,在那種情況下,CQRS 可能是一個合適的選擇,盡管沒有手頭的規范很難說。

我不希望整個服務都按順序處理呼叫,因為這會損害客戶端的性能(某些呼叫可能需要3-4秒來處理)。 那么我的解決方案是什么?

然后,如果可以,請使用PerCall實例化和單個或多個並發。 在此處查看有關實例化/並發組合的詳細信息。

對具有“多個”線程的所有客戶端使用“單個”實例,然后使用鎖定對象? 這不是序列化的結果嗎?

單實例化將為您帶來並發性問題,請參閱我上面鏈接的文章。 如果您需要Singleton服務,它通常很有用。


更新

回答您的評論:恐怕我仍然不明白您期望在哪里出現並發問題。 如果您擔心WCF服務,只需避免使用單實例化:最具擴展性的選項是PerCall / Multiple。

如果您問自己是否需要考慮CQRS,請隨時閱讀我在另一條評論中鏈接的Udi Dahan文章 但是請記住,CQRS需要花費一些時間才能完成,並增加了您可能需要或可能不需要的項目復雜性。

我建議不要不必要地使您的體系結構復雜化,對我來說,聽起來像為服務正確配置實例/並發就足夠了。 如果不確定,請編寫一些原型以使系統達到預期的負載。 更好的安全性是對不起,特別是如果它將是一個長期存在的應用程序時。

暫無
暫無

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

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