# 云計算設計模式(三)——補償交易模式
撤消由一系列步驟,它們共同限定了最終一致性操作中,如果一個或多個步驟失敗執行的工作。按照最終一致性模型,業務實現復雜的業務流程和工作流的云托管的應用程序中很常見。
## 背景和問題
在云中運行的應用程序頻繁修改數據。此數據可跨在各種地理位置的所保持的數據源的一個品種傳播。為了避免爭用,并提高在分布式環境中,例如這樣的性能,應用程序不應該試圖提供強事務一致性。相反,應用程序應該實現最終一致性。在該模型中,一個典型的業務操作由一系列的獨立的步驟。而正在執行這些步驟的系統狀態的整體圖可能是不一致的,但是,當操作完成并且所有步驟都被執行,系統應該重新變得一致。
**注意**
數據的一致性提供了入門為什么分布式事務不能很好地擴展更多的信息,并且鞏固了最終一致性模型的原則。
在最終一致性模型的一個顯著的挑戰是如何處理失敗無可挽回的一步。在這種情況下,可能需要撤消所有通過的操作中的前面的步驟完成的工作。然而,數據不能簡單地被回滾,因為應用程序的其它并發實例可能已經改變,因為它。即使在數據沒有被通過一并發實例變更的情況下,撤消一個步驟可能不是簡單地恢復原始狀態的問題。可能需要應用不同的業務特定的規則(參見實施例部分中描述的旅行網站)。
如果實現最終一致性操作跨越多個異構數據存儲,解開在這樣的操作中的步驟將需要訪問的每個數據存儲區中的轉彎。在每一個數據存儲區執行的工作必須可靠地復原到防止系統其余不一致。
不受實現最終一致性的操作的所有數據可能會在數據庫中進行。在面向服務的架構(SOA)環境中的操作可能會調用一個服務動作,并導致由該服務保持狀態的變化。要撤消的操作,這種狀態的改變也必須是百廢待興。這可能涉及再次調用服務并執行該反轉第一的影響另一個動作。
## 解決方案
落實補償事務。在一個補償事務的步驟必須撤消的原始操作的步驟的影響。補償事務可能無法簡單地與國家的制度在運行,因為這種方法可能會覆蓋由應用程序的其他并發實例所做的更改開始取代目前的狀態。相反,它必須是一個聰明的過程中,考慮到并發情況下進行的任何工作。這個過程通常是應用程序特定的,由原始操作所執行的工作的性質來驅動。
一種常見的方法來實現的,最終一致的操作,需要補償的是使用的工作流。由于原來的動作的進行,系統記錄每個步驟,以及如何通過該步驟完成的工作可以撤消信息。如果操作失敗,在任何時候,在工作流倒卷回通過它已經完成的步驟,并執行反轉每個步驟的工作。注意,補償事務可能沒有撤消的原始操作的精確鏡面相反的順序工作,并且它可能會執行一些并行撤銷步驟。
**注意**
這種方法類似于英雄傳奇策略。這一戰略的描述是克萊門斯 Vasters 的博客在網上提供。
補償事務本身是一個最終一致的操作,它也可能會失敗。該系統應能夠恢復補償事務在故障點并繼續。可能有必要重復發生故障的步驟,所以在補償事務的步驟應該被定義為冪等的命令。有關冪等的詳細信息,請參閱喬納森·奧利弗的博客冪等模式??。
在某些情況下,可能無法從該已失敗,除非通過人工干預的步驟中恢復。在這種情況下,系統應發出警報,并提供盡可能多的信息盡可能了解失敗的原因。
## 問題和注意事項
在決定如何實現這個模式時,請考慮以下幾點:
- 它可能不容易確定何時在實現最終一致性的動作的步驟已經失敗。一個步驟可能不會立即失敗,而是它可以阻止。可能有必要實現某種形式的超時機制。
- 補償邏輯不容易推廣。補償事務是特定于應用程序;它依賴于具有足夠的信息,以便能夠撤消在一個失敗的操作的每個步驟的效果的應用。
- 您應該定義的步驟在補償事務的冪等命令。這使得,如果補償事務本身不能被重復的步驟。
- 處理中原始操作的步驟,以及所述補償事務的基礎設施,必須是有彈性的。它一定不能失去,以補償發生故障的步驟所需要的信息,而且它必須能夠可靠地監視補償邏輯的進度。
- 一個補償事務并不一定在系統中返回數據的狀態是在原操作的開始。相反,它補償了由該成功完成操作失敗之前的步驟中執行的工作。
- 在補償事務中的步驟的順序并不一定是反射鏡相反的,在原來的操作的步驟。例如,一個數據存儲可以是不一致比另一個更敏感,從而撤消更改到該商店中的補償事務的步驟應首先發生。
- 在完成操作所需的每個資源放置一個短期的基于超時的鎖,并提前獲得這些資源,可以幫助增加的可能性,整體活動將取得成功。這項工作應執行的所有資源都被收購之后。所有操作必須完成的鎖到期之前。
- 考慮使用重試邏輯比平常更多的寬容,盡量減少觸發補償事務失敗。如果一個操作步驟,實現最終一致性失敗,請嘗試處理故障為一過性異常,并重復上述步驟。只有放棄操作,如果一個步驟反復或無可挽回地失敗,啟動補償事務。
> 注意: 很多的挑戰和實施補償事務的問題是一樣關心實現最終一致性。請參見注意事項實現了數據的一致性入門最終一致性的更多信息。
## 當使用這個模式
使用此模式僅適用于如果他們失敗,必須撤銷的操作。如果可能的話,設計解決方案,避免了需要補償事務的復雜性(有關詳細信息,請參閱數據一致性底漆)。
## 例子
一個旅游網站,使客戶預訂行程。一個單一的行程可包括一系列航班和酒店的。一位顧客旅行從西雅圖到倫敦及巴黎可以創建一個行程時,請執行以下步驟:
1.預訂一個座位上的 F1 航班從西雅圖飛往倫敦。
2.預訂一個座位上的 F2 航班從倫敦到巴黎。
3.書本占座 F3 航班從巴黎飛往西雅圖。
4.預訂的房間在倫敦酒店 H1。
5.預訂在巴黎一間客房的酒店 H2。
這些步驟構成了最終一致的操作,雖然每一步基本上是在自己的權利單獨的原子操作。因此,以及在執行這些步驟時,系統還必須記錄必要撤消各以防客戶決定取消行程步驟計數器的操作。必要執行計數器操作步驟,然后可以作為一個補償事務如有必要運行。
請注意,在補償事務中的步驟可能不是原來的步驟完全相反,并且在補償事務的每個步驟必須考慮到任何特定于業務的邏輯規則。例如,“unbooking 取消預訂”座位上的飛行可能不是客戶有權向支付任何款項完成退款。

圖1 - 生成一個補償事務撤消一個長時間運行的事務預訂旅游行程
### Note
它可能會在并行執行的補償事務的步驟,這取決于你如何設計每一步的補償邏輯。
在許多商業解決方案,在單步的故障不總是必要軋制系統背面用補償事務。例如,具有在旅游網站的情況,客戶是無法預訂到酒店H1預訂航班 F1,F2 和 F3 的話,以后,最好是提供客戶在同一個城市的房間在不同的酒店而不是取消航班。客戶仍然可以選擇取消(在這種情況下,補償事務運行,并撤消作出關于航班 F1,F2 和 F3中的預訂),但這個決定應該由客戶而不是由系統進行。
- 前言
- (一)—— 緩存預留模式
- (二)—— 斷路器模式
- (三)—— 補償交易模式
- (四)——消費者的競爭模式
- (五)——計算資源整合模式
- (六)——命令和查詢職責分離(CQRS)模式
- (七)——事件獲取模式
- (八)——外部配置存儲模式
- (九)—— 聯合身份模式
- (十)——守門員模式
- (十一)—— 健康端點監控模式
- (十二)—— 索引表模式
- (十三)——領導人選舉模式
- (十四)——實體化視圖模式
- (十五)—— 管道和過濾器模式
- (十六)——優先級隊列模式
- (十七)—— 基于隊列的負載均衡模式
- (十八)—— 重試模式
- (十九)——運行重構模式
- (二十)—— 調度程序代理管理者模式
- (二十一)——Sharding 分片模式
- (二十二)——靜態內容托管模式
- (二十三)——Throttling 節流模式
- (二十四)—— 仆人鍵模式