博客 / 詳情

返回

分佈式系統架構3:服務容錯

這是小卷對分佈式系統架構學習的第3篇文章,雖然知道大家都不喜歡看純技術文章,寫了也沒多少閲讀量,但是個人要成長的話,還是需要往深一點的技術上去探索的

1.為什麼需要容錯

分佈式系統的本質是不可靠的,一個大的服務集羣中,程序可能崩潰、節點可能宕機、網絡可能中斷,這些“意外情況”其實全部都在“意料之中”。故障的發生是必然的,所以需要設計一套健壯的容錯機制來應對這些問題。

容錯策略,指的是“面對故障,我們該做些什麼”;而容錯設計模式,指的是“要實現某種容錯策略,我們該如何去做”。下面介紹7種常見的容錯策略。

2.七種容錯策略

7種常見的容錯策略:故障轉移、快速失敗、安全失敗、沉默失敗、故障恢復、並行調用和廣播調用

故障轉移Failover

概念:分佈式服務中,服務會有多個副本。如果調用的服務器出現故障,系統不會直接返回失敗,而是切換到其他服務副本上,保證返回調用成功的結果。

故障轉移需要設置重試次數,並且需根據實際業務場景考慮是否設置故障轉移。示例:

現在有 Service A → Service B → Service C 這麼一條調用鏈。假設 A 的超時閾值為 100ms,而 B 調用 C 需要 60ms,然後不幸失敗了,這時候做故障轉移其實已經沒有太大意義了。因為即使B調用C故障轉移成功了,調用耗時至少增加60ms,A已經超時了,這種故障轉移對系統無利。

適用場景:讀多寫少的採集,如:電商商品查詢;對成功率要求高的採集

快速失敗Failfast

當業務場景不允許,或者服務是非冪等時,重複調用會產生髒數據,就不能用故障轉移了,需要用到快速失敗。

概念:服務在調用失敗後,立即返回錯誤,不做任何重試

示例:支付場景中,調用銀行扣款接口,返回結果是網絡異常。這時候無法區分是否已扣款了,為避免重複扣款,只能服務拋出異常報錯,不能重試

適用場景:高實時性場景、交易支付場景

缺點:調用方需有較高容錯能力

安全失敗Failsafe

服務也區分主路和旁路,旁路的特點是服務失敗了也不影響核心業務。比如spring項目中的日誌、Debug信息等。旁路邏輯不影響最終結果。因此,對這類邏輯的容錯策略就是,即使旁路邏輯失敗了,也當做正確返回。

概念:當服務調用失敗時,忽略異常並返回一個默認的結果,確保系統繼續運行。

適用場景:非核心業務場景,日誌處理、監控採集

優點:最大化保證系統穩定性

示例:java中的try-catch,Dubbo中的failsafe策略

沉默失敗Failsilent

概念:大量請求如果都等到超時才失敗,可能將系統的線程、內存、網絡資源耗盡,影響整個服務穩定性。對該場景的失敗策略是:當請求失敗後,默認服務提供者一定時間內無法提供服務了,不再向它分配流量,將錯誤隔離開來。

實際應用場景:分佈式系統中,單點故障時,流量調度系統不再給該節點分配流量,每隔5分鐘自動檢查節點是否恢復。

故障恢復Failback

不是單獨存在的,通常默認使用快速失敗+故障恢復策略

概念:故障恢復是指在服務調用失敗後,將失敗的請求異步存儲下來,存到數據庫或消息隊列中,並定時重試或補償,直到調用成功。這種方式對業務具有一定的“追溯”能力。故障恢復也需有最大重試次數限制

適用場景:實時性要求不高,數據一致性要求高的場景。如:庫存更新、訂單狀態同步

優點:提高系統最終一致性

缺點:系統需配合消息隊列,實現複雜

小結:前面5種容錯策略都是針對調用失敗後如何進行彌補的,下面2種是調用之前如何提供成功率的

並行調用Forking

概念:同時調用多個服務節點,只要任意一個節點返回成功結果即認為調用成功。對於調用結果相同或相似的服務節點,這種方式可大幅提高調用成功率。

適用場景:多副本部署場景、調用耗時長且高可用要求的場景。如:數據庫分片存儲查詢

優點:提供成功率,減少等待時間(取決於最先返回成功的節點)

缺點:增加系統開銷

廣播調用Broadcast

概念:請求發送給所有服務實例,並收集所有返回結果,要求所有請求全部成功才算成功。這種方式適用於需要對多個節點進行同步操作的場景

適用場景:刷新分佈式緩存、配置同步

優點:所有節點都能執行操作

缺點:並行執行開銷大

實現方式:Dubbo的broadcast策略支持廣播調用

7種容錯策略對比

容錯策略 優點 缺點 應用場景
故障轉移 系統自動處理,調用者對失敗信息不可見 會增加調用時間,也會導致額外的資源開銷 調用冪等服務,對調用時間不敏感的場景
快速失敗 調用者有失敗的處理完全控制,不依賴服務的冪等性 調用者必須正確處理失敗邏輯,容易引起雪崩 調用非冪等的服務,超時閾值較低的場景
安全失敗 不影響主邏輯 只適用於旁路調用 調用鏈中的旁路服務
沉默失敗 控制錯誤不影響全局 出錯的地方將有一段時間內不可用 頻繁超時的服務
故障恢復 調用失敗後自動重試,也不影響主邏輯 推薦用於旁路服務調用,重試任務可能堆積,重試仍然可能失敗 調用鏈中的旁路服務,對實時性要求不高的主邏輯
並行調用 儘可能在最短時間內獲得最高的成功率 額外消耗機器資源,大部分調用可能是無用功 資源充足且失效容忍度低的場景
廣播調用 支持同時對批量的服務提供者發起調用 資源消耗大,失敗概率高 只適用於批量操作的場景

面試題準備

如果一個業務系統需要調用第三方的5個接口,這5個接口中只要有3個接口返回成功了就認為成功,問如何設計並實現

周志明大佬的答覆:

我看這題是個圈套呀,大多數的架構設計題目,固定答案往往都是不對的。因為做技術設計是為了解決實際問題,不能談兵,所以方案要根據希望實現的目標而定:

如果目的是這項業務儘可能快速地完成,那就forking策略,5個一起調用,成功3個算過。

如果目的是這項業務儘可能少消耗資源,那就failfast策略,先對它們出錯概率做個先驗判斷,排序後先調用最容易出錯的,錯夠3次算失敗,後面的不執行。

如果目的是這項業務儘可能高概率地完成,那就failover策略

user avatar lankerens 頭像 codingdgsun 頭像 prepared 頭像 mokeywie 頭像 buxiyan 頭像 tengteng_5c7902af4b01e 頭像 async_wait 頭像 qiehxb8 頭像 u_16213560 頭像 fedl 頭像 nahandechaomian 頭像 fanjiapeng 頭像
17 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.