<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 云計算設計模式(六)——命令和查詢職責分離(CQRS)模式 隔離,通過使用不同的接口,從操作讀取數據更新數據的操作。這種模式可以最大限度地提高性能,可擴展性和安全性;支持系統在通過較高的靈活性,時間的演變;防止更新命令,從造成合并在域級別上的沖突。 ## 背景和問題 在傳統的數據管理系統中,這兩個命令(更新數據)和查詢(請求數據),針對在一個單一的數據存儲庫中的相同的一組實體的執行。這些實體可以是在關系數據庫中的一個或多個表,如 SQL Server 的行的子集。 典型地,在這些系統中,所有的創建,讀取,更新和刪除(CRUD)操作被施加到該實體的相同的表示。例如,一個數據傳輸對象(DTO)的代表顧客從數據存儲中檢索由數據訪問層(DAL)并顯示在屏幕上。用戶更新 DTO 的某些領域(也許是通過數據綁定)和 DTO,然后保存回數據存儲在 DAL。相同的 DTO 同時用于讀取和寫入操作,如圖1所示。 ![](https://box.kancloud.cn/2015-09-21_55ffa42eaa049.png) 圖1 - 一個傳統的 CRUD 架構 傳統的 CRUD 設計工作良好時,只有施加到數據操作有限的業務邏輯。由開發工具提供可以非常快速地創建數據訪問代碼的支架機構,根據需要,可再進行定制。 然而,傳統的 CRUD 方法有一些缺點: - 它往往意味著存在所述讀取和寫入的數據,如額外的列或屬性,即使它們不是必需的作為操作的一部分,必須正確地更新的表示之間的不匹配。 - 它遇到風險的數據爭用一個協作領域(在多個參與者??并行運行在相同的數據集)時,記錄被鎖定在數據存儲,或者更新沖突所造成的并發更新時,樂觀鎖使用。這些風險增加的復雜性和系統的吞吐量增加。此外,傳統的方法也可以對性能有負面影響,由于加載的數據存儲和數據訪問層上,并在檢索信息需要查詢的復雜度。 - 它可以使安全管理和權限比較繁瑣,因為每一個實體是受讀取和寫入操作,這可能會在不經意間暴露的數據在錯誤的情況下。 > 注意: 對于的 CRUD 方法的局限性有了更深的了解請參見“CRUD,只有當你能負擔得起”MSDN 上。 ## 解決方案 命令和查詢職責分離(CQRS)是偏析,通過使用獨立的接口讀取操作的更新數據(命令)的數據(查詢)的操作模式。這意味著,用于查詢和更新的數據模型是不同的。該模型可隨后被分離,如在圖 2 中,雖然這不是絕對的要求。 ![](https://box.kancloud.cn/2015-09-21_55ffa42eb450a.png) 圖2 - 一個基本的 CQRS 架構 相比于數據(從該開發商建立自己的概念模式)的單個模型中固有的 CRUD 為基礎的系統中,使用單獨的查詢和更新模型中 CQRS 為基礎的系統中的數據顯著地簡化設計和實施。然而,一個缺點是,不像 CRUD 的設計,CQRS 代碼不能自動用支架的機制產生。 查詢模型讀取數據和寫入數據可以訪問相同的實體店,也許是通過使用 SQL 視圖的更新模型,或產生對飛預測。但是,它是常見的數據分成不同的物理存儲來提高性能,可擴展性和安全性;如圖3。 ![](https://box.kancloud.cn/2015-09-21_55ffa42ec3dca.png) 圖3 - 一個 CQRS 架構,具有獨立讀寫店 所讀取的存儲可以是只讀副本寫入存儲區,或讀取和寫入存儲可以具有不同的結構完全。使用 read 店的多個只讀副本可以大大提高查詢性能和應用程序的UI響應速度,尤其是在分布式場景下的只讀副本靠近應用程序實例。一些數據庫系統,如 SQL Server,提供額外的功能,如故障轉移副本,以最大限度地提高可用性。 讀的分離和寫入存儲還允許每個到會適當縮放以匹配負載。例如,讀取存儲通常會遇到一個更高的負載寫入存儲。 當查詢/讀取模型中包含的非規范化的信息(見物化視圖模式),性能正在讀取數據的每一個視圖時在應用程序中或在查詢系統中的數據時最大化。 有關CQRS模式及其實現的詳細信息,請參閱以下資源: - 該模式與實踐指導 CQRS 之旅 MSDN 上。尤其是你應該閱讀的章節介紹了命令查詢職責分離方式進行全面的探索模式,當它是有用的,這一章尾聲:經驗教訓,了解一些,可以使用這種模式時出現的問題。 - 該職位 CQRS 由馬丁·福勒,這也解釋了該模式的基本知識,并鏈接到其他一些有用的資源。 - 代碼更好的網站,它探討的 CQRS 模式的許多方面對 Greg Young 的帖子。 ## 問題和注意事項 在決定如何實現這個模式時,請考慮以下幾點: - 分割數據存儲到單獨的物理存儲用于讀操作和寫操作可以提高系統的性能和安全性,但它可以在彈性和最終一致性方面增加了相當大的復雜性。所讀取的模型存儲必須被更新以反映變化的寫入模型存儲,并且它可以是難以檢測用戶何時發出基于讀取過時數據意味著該操作不能完成的請求。 ### 注意 對于最終一致性的說明,請參閱數據一致性底漆。 - 考慮 CQRS 應用到你的系統中的限制部分地方將是最有價值的,并從經驗中學習。 - 的典型方法擁抱最終一致性是使用事件采購與 CQRS 結合使寫模式是由執行命令的驅動事件的追加只流。這些事件被用來更新充當讀取模型化視圖。欲了解更多信息,請參閱事件獲取和 CQRS。 ## 當使用這個模式 這種模式非常適合于: - 其中并行地對相同的數據進行多項操作協同域。 CQRS 允許你有足夠的粒度定義的命令,以盡量減少在域級別(或者不出現可以通過在命令合并的沖突)的合并沖突,更新這似乎是同一類型的數據時也是如此。 - 使用與基于任務的用戶界面(其中用戶通過一個復雜的過程引導作為一系列步驟),具有復雜的領域模型,以及用于團隊已經熟悉領域驅動設計(DDD)技術。在寫入模式有一個完整的命令處理棧與業務邏輯,輸入驗證和業務驗證,以確保一切總是為每個聚集體(被視為一個單元進行數據變更的目的相關聯的對象的每個集群相一致)中的寫入模式。讀出的模型沒有業務邏輯或驗證的堆棧,只是返回一個 DTO 在一個視圖模型的使用。讀出的模型與模型寫入最終一致。 - 方案,其中數據的讀出性能,必須分別從數據的性能進行微調寫入,尤其是當讀/寫比是非常高的,并且當水平擴展是必要的。例如,在許多系統中的讀取操作的數目是幾個數量級更大的寫入操作的數目。為了適應這種情況,考慮向外擴展的讀取模式,但只在一個或幾個實例中運行的寫模式。少數寫入模型實例也有助于減少合并沖突的發生。 - 場景的開發者之一的團隊可以專注于復雜的領域模型,它是寫模型的一部分??,而另一個經驗不足的團隊可以專注于讀模型和用戶界面。 - 場景中,預計隨著時間的推移,系統,并且可以包含多個版本的模型,或者業務規則經常改變。 - 與其他系統,特別是與事件采購,其中一個子系統的瞬時故障不會影響到其它的可用性的組合一體化。 這種模式可能不適合于下列情況: - 凡域或業務規則很簡單。 - 凡一個簡單的 CRUD 風格的用戶界面和相關的數據訪問操作就足夠了。 - 對于在整個系統中的實現。有一個整體的數據管理方案,其中 CQRS 可以是有用的特定組件,但是它可以增加它實際上并不需要相當大的和往往是不必要的復雜性。 ## 事件獲取和 CQRS CQRS 模式常用于與事件獲取圖案一起使用。 CQRS 為基礎的系統使用分離的讀取和寫入的數據模型,每個針對有關任務和通常位于物理上分離的存儲區。當與采購活動時,事件的存儲是寫模式,這是信息的權威來源。一個 CQRS 為基礎的系統的讀取模型提供數據的物化視圖,通常是高度非規范化的意見。這些視圖量身定做的接口和應用程序,這有助于最大程度地顯示和查詢性能的顯示要求。 使用事件作為寫入存儲區,而不是實際的數據的流,在一個時間點,避免了在單個聚合更新沖突并最大限度地提高性能和可擴展性。該事件可用于異步生成用于填充讀取存儲器中的數據的實體化視圖。 由于事件存儲是信息的權威來源,就可以刪除物化視圖和回放所有過去的事件來創建當前狀態的一個新表示當系統升級時,或者當讀取模式必須改變。物化視圖是有效的數據的耐用只讀緩存。 當使用 CQRS 結合事件獲取模式,考慮以下幾點: - 與任何系統,其中寫入和讀出存儲是分開的,在此基礎上圖案系統唯一最終一致。將有被生成的事件和數據存儲器保存由這些事件被更新啟動操作的結果之間有一些延遲。 - 該模式引入由于代碼必須創建啟動和處理事件,并組裝或者更新查詢或讀取模型所需的適當的意見或物體額外的復雜性。在采購活動一起使用的 CQRS 模式固有的復雜性時,可以做一個成功的實現更加困難,需要重新學習的一些概念和不同的方法來設計系統。然而,事件采購可以更容易地對域進行建模,并且可以更容易地重建的觀點或創建新的,因為變化的數據的意圖將被保留。 - 生成物化視圖中讀取模型或數據通過重放和處理為特定的實體或實體的集合的事件突起的使用可能需要相當多的處理時間和資源的使用,尤其是如果它需要求和或值的數據在長時間內的,因為所有的相關聯的事件可能需要被審查。這可以通過實現數據的快照在預定的時間間隔,如已經發生的特定操作的次數,或一個實體的當前狀態的總計數被部分地解決。 > 注意: 欲了解更多信息,請參閱活動采購模式和物化視圖模式,以及模式與實踐指導 CQRS 之旅 MSDN 上。尤其是你應該閱讀的章節介紹采購活動進行全面的探索模式,以及它如何與 CQRS 有用的,而章 CQRS 和 ES 深潛了解更多,包括如何聚集分區可以在微軟的 Azure CQRS 使用。 ## 例子 下面的代碼顯示了一個 CQRS 實現,它使用不同的定義讀取和寫入模型為例某些提取物。該模型的接口沒有規定的基礎數據存儲的任何功能,并且可以發展和進行微調獨立,因為這些接口是分開的。 下面的代碼演示了讀取的模型定義。 ~~~ // Query interface namespace ReadModel { public interface ProductsDao { ProductDisplay FindById(int productId); IEnumerable<ProductDisplay> FindByName(string name); IEnumerable<ProductInventory> FindOutOfStockProducts(); IEnumerable<ProductDisplay> FindRelatedProducts(int productId); } ? public class ProductDisplay { public int ID { get; set; } public string Name { get; set; } public string Description { get; set; } public decimal UnitPrice { get; set; } public bool IsOutOfStock { get; set; } public double UserRating { get; set; } } ? public class ProductInventory { public int ID { get; set; } public string Name { get; set; } public int CurrentStock { get; set; } } } ~~~ 該系統允許用戶率的產品。應用程序代碼通過使用在下面的代碼中所示的 RateProduct 命令執行此操作。 ~~~ public interface Icommand { Guid Id { get; } } ? public class RateProduct : Icommand { public RateProduct() { this.Id = Guid.NewGuid(); } public Guid Id { get; set; } public int ProductId { get; set; } public int rating { get; set; } public int UserId {get; set; } } ~~~ 本系統采用 ProductsCommandHandler 類來處理由應用程序發出的命令。客戶端通常通過消息傳送系統發送命令到域,如一個隊列。命令處理程序接受這些命令,并調用域接口的方法。每個命令的粒度被設計成減輕沖突請求的機會。下面的代碼顯示了 ProductsCommandHandler 類的輪廓。 ~~~ public class ProductsCommandHandler : ICommandHandler<AddNewProduct>, ICommandHandler<RateProduct>, ICommandHandler<AddToInventory>, ICommandHandler<ConfirmItemShipped>, ICommandHandler<UpdateStockFromInventoryRecount> { private readonly IRepository<Product> repository; ? public ProductsCommandHandler (IRepository<Product> repository) { this.repository = repository; } ? void Handle (AddNewProduct command) { ... } ? void Handle (RateProduct command) { var product = repository.Find(command.ProductId); if (product != null) { product.RateProuct(command.UserId, command.rating); repository.Save(product); } } ? void Handle (AddToInventory command) { ... } ? void Handle (ConfirmItemsShipped command) { ... } ? void Handle (UpdateStockFromInventoryRecount command) { ... } } ~~~ 下面的代碼顯示了寫模式 ProductsDoman 接口。 ~~~ public interface ProductsDomain { void AddNewProduct(int id, string name, string description, decimal price); void RateProduct(int userId int rating); void AddToInventory(int productId, int quantity); void ConfirmItemsShipped(int productId, int quantity); void UpdateStockFromInventoryRecount(int productId, int updatedQuantity); } ~~~ 還要注意如何 ProductsDomain 接口包含在域中的意義的方法。通常情況下,在一個 CRUD 環境中,這些方法將有通用名稱,如保存或更新,并有一個 DTO 作為唯一的參數。該 CQRS 方法可以更好地定制,以滿足該組織開展業務及庫存管理的方式。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看