補償交易模式

Azure

當您使用由一系列步驟組成的最終一致作業時,補償交易模式可能會很有用。 具體而言,如果一或多個步驟失敗,您可以使用補償交易模式來復原步驟執行的工作。 一般而言,您會在雲端裝載應用程式中找到遵循最終一致性模型的作業,以實作複雜的商務程式和工作流程。

內容和問題

在雲端中執行的應用程式經常修改資料。 此資料有時會分散到不同地理位置的各種資料來源。 為了避免分散式環境中出現競爭並改善效能,應用程式不應嘗試提供強式交易一致性。 相反地,應用程式應實作最終一致性。 在最終一致性模型中,典型的商務作業是由一系列個別步驟所組成。 雖然作業會執行這些步驟,但系統狀態的整體檢視可能不一致。 但是當作業完成且所有步驟都已執行時,系統應該會再次保持一致。

資料一致性入門提供分散式交易為何無法妥善調整的資訊。 此資源也會列出最終一致性模型的原則。

最終一致性模型中的挑戰是如何處理失敗的步驟。 失敗之後,您可能需要復原作業中先前步驟完成的所有工作。 不過,您無法一律回復資料,因為應用程式的其他並行實例可能已經變更。 即使並行實例尚未變更資料,復原步驟可能比還原原始狀態更為複雜。 可能需要套用各種商務特定規則。 如需範例,請參閱本文稍後的「 範例 」一節所描述的旅遊網站。

如果實作最終一致性的作業跨越數個異質資料存放區,復原作業中的步驟需要接著流覽每個資料存放區。 若要防止系統保持不一致,您必須可靠地復原您在每個資料存放區中執行的工作。

實作最終一致性之作業所影響的資料不一定會保留在資料庫中。 例如,假設服務導向架構 (SOA) 環境。 SOA 作業可以在服務中叫用動作,並造成該服務所持有的狀態變更。 若要復原作業,您也必須復原此狀態變更。 此程式可能會牽涉到再次叫用服務,並執行另一個動作來反轉第一個的效果。

解決方法

解決方式就是實作補償交易。 補償交易中的步驟會復原原始作業中步驟的效果。 直覺式方法是將目前狀態取代為系統在作業開始時的狀態。 但補償交易不一定會採用該方法,因為它可能會覆寫應用程式其他並行實例所做的變更。 相反地,補償交易必須是智慧型進程,以考慮並行實例執行的任何工作。 此程式通常是應用程式特定的,由原始作業執行的工作本質所驅動。

常見的方法是使用工作流程來實作需要補償的最終一致性作業。 當原始作業繼續進行時,系統會記錄每個步驟的相關資訊,包括如何復原步驟執行的工作。 如果作業在任何時間點失敗,工作流程會透過已完成的步驟回復。 在每個步驟中,工作流程都會執行反轉該步驟的工作。

兩個重要重點包括:

  • 補償交易可能不需要以原始作業的確切反向順序復原工作。
  • 您可以平行執行一些復原步驟。

這種方法類似于 Clemens Vasters 部落格中討論的 Sagas 策略。

補償交易是最終一致的作業本身,因此也可以失敗。 系統應能夠在失敗時恢復補償交易並繼續。 您可能需要重複失敗的步驟,因此您應該將補償交易中的步驟定義為等冪命令。 如需詳細資訊,請參閱 Jonathan Oliver 部落格上的 等冪模式

在某些情況下,手動介入可能是從失敗的步驟中復原的唯一方法。 在這些情況下,系統應該引發警示,並盡可能提供有關失敗原因的資訊。

問題和考量

當您決定如何實作此模式時,請考慮下列幾點:

  • 當實作最終一致性的作業中的步驟失敗時,可能不容易判斷。 步驟可能不會立即失敗。 相反地,它可能會遭到封鎖。 您可能需要實作逾時機制。

  • 一般化補償邏輯並不容易。 補償交易是應用程式特定的。 全賴應用程式有足夠的資訊,才能復原失敗作業中每個步驟的效果。

  • 您應該將補償交易中的步驟定義為等冪命令。 如果您這麼做,如果補償交易本身失敗,可以重複這些步驟。

  • 處理步驟的基礎結構必須符合下列準則:

    • 它在原始作業和補償交易中具有復原性。
    • 它不會遺失補償失敗步驟所需的資訊。
    • 它會可靠地監視補償邏輯的進度。
  • 補償交易不一定會在原始作業開始時,將系統資料傳回其狀態。 相反地,交易會補償作業在失敗前成功完成的工作。

  • 補償交易中的步驟順序不一定與原始作業中的步驟完全相同。 例如,一個資料存放區可能會比另一個資料存放區更敏感。 復原此存放區變更之補償交易中的步驟應該先發生。

  • 某些量值有助於增加整體活動成功的可能性。 具體來說,您可以針對完成作業所需的每個資源,放置短期、逾時型鎖定。 您也可以事先取得這些資源。 然後,只有在您取得所有資源之後,才執行工作。 在鎖定到期之前完成所有動作。

  • 比平常更適合的重試邏輯,有助於將觸發補償交易的失敗降到最低。 如果實作最終一致性的作業中的步驟失敗,請嘗試將失敗視為暫時性例外狀況並重複步驟。 只有在重複或無法復原步驟時,才停止作業並起始補償交易。

  • 當您實作補償交易時,您會面臨許多您在實作最終一致性時遇到的相同挑戰。 如需詳細資訊,請參閱 資料一致性入門中的一節。

使用此模式的時機

只針對失敗時必須復原的作業使用此模式。 設計解決方案時,請盡量避免採用複雜的補償交易。

範例

客戶會使用旅遊網站來預訂路線。 單一路線可能包含一系列航班和旅館。 從西雅圖到倫敦,然後前往巴黎的客戶可能會在建立行程時執行下列步驟:

  1. 預訂從西雅圖飛往倫敦的 F1 航班座位。
  2. 預訂從倫敦飛往巴黎的 F2 航班座位。
  3. 預訂從巴黎飛往西雅圖的 F3 航班座位。
  4. 在倫敦的 H1 旅館訂房。
  5. 在巴黎的 H2 旅館訂房。

雖然每個步驟都是個別的動作,但這些步驟會構成最終一致性作業。 除了執行這些步驟之外,系統也必須記錄計數器作業,以復原每個步驟。 如果客戶取消路線,則需要此資訊。 然後,執行計數器作業所需的步驟就可以以補償交易的形式執行。

補償交易中的步驟可能與原始步驟完全相同。 此外,補償交易中每個步驟中的邏輯都必須考慮商務特定規則。 例如,取消航班保留可能無法讓客戶獲得完整的退款。

下圖顯示預約旅遊行程長時間執行交易中的步驟。 您也可以查看復原交易的補償交易步驟。

此圖顯示建立路線的步驟。也會顯示取消行程之補償交易的步驟。

注意

視您設計每個步驟的補償邏輯方式而定,您可能可以平行執行補償交易中的步驟。

在許多商務解決方案中,單一步驟失敗不一定需要使用補償交易來回複系統。 例如,請考慮旅遊網站案例。 假設客戶預訂正式發行前小眾測試版 F1、F2 和 F3,但無法保留旅館 H1 的會議室。 最好是在相同城市的不同旅館為客戶提供房間,而不是取消航班。 客戶仍然可以決定取消。 在此情況下,補償交易會執行並復原航班 F1、F2 和 F3 的預約。 但客戶應該做出此決策,而不是系統。

下一步

  • 資料一致性入門。 補償交易模式通常用來復原實作最終一致性模型的作業。 此入門提供最終一致性優點和取捨的相關資訊。
  • 等冪模式。 在補償交易中,最好使用等冪命令。 此部落格文章說明實作等冪時應考慮的因素。
  • 排程器代理程式監督員模式。 本文說明如何實作復原系統,以執行使用分散式服務和資源的商務作業。 在這些系統中,您有時需要使用補償交易來復原作業執行的工作。
  • 重試模式。 補償交易可能需要計算。 您可以使用重試模式來嘗試盡可能減少其使用狀況,以實作重試失敗作業的有效原則。
  • Saga 分散式交易模式。 本文說明如何使用 Saga 模式來管理分散式交易案例中微服務之間的資料一致性。 Saga 模式會處理補償交易的失敗復原。
  • 管道和篩選模式。 本文說明管道和篩選模式,您可以使用此模式將複雜的處理工作分解成一系列可重複使用的專案。 您可以使用管道和篩選模式搭配補償交易模式,作為實作分散式交易的替代方案。
  • 自我修復設計 。 本指南說明如何設計自我修復應用程式。 您可以使用補償交易作為自我修復方法的一部分。