彈力設計之降級設計

所謂的降級設計(Degradation),本質是爲了解決資源不足和訪問量過大的問題。當資源和訪問量出現矛盾的時候,在有限的資源下,爲了能夠扛住大量的請求,我們就需要對系統進行降級操作。也就是說,暫時犧牲掉一些東西,以保障整個系統的平穩運行。

一般來說,我們的降級需要犧牲掉的東西有:

  • 降低一致性。從強一致性變成最終一致性。
  • 停止次要功能。停止訪問不重要的功能,從而釋放出更多的資源。
  • 簡化功能。把一些功能簡化掉,比如,簡化業務流程,或是不再返回全量數據,只返回部分數據。

降低一致性

我們要清楚地認識到,這世界上大多數系統並不是都需要強一致性的。對於降低一致性,把強一致性變成最終一致性的做法可以有效地釋放資源,並且讓系統運行得更快,從而可以扛住更大的流量。一般來說,會有兩種做法,一種是簡化流程的一致性,一種是降低數據的一致性。

使用異步簡化流程

舉個例子,比如電商的下單交易系統,在強一致的情況下,需要結算賬單,扣除庫存,扣除賬戶上的餘額(或發起支付),最後進行發貨流程,這一系列的操作。

如果需要是強一致性的,那麼就會非常慢。尤其是支付環節可能會涉及銀行方面的接口性能,就像雙 11 那樣,銀行方面出問題會導致支付不成功,而訂單流程不能往下走。

在系統降級時,我們可以把這一系列的操作做成異步的,快速結算訂單,不佔庫存,然後把在線支付降級成用戶到付,這樣就省去支付環節,然後批量處理用戶的訂單,向用戶發貨,用戶貨到付款。

一般來說,功能降級都有可能會損害用戶的體驗,所以,最好給出友好的用戶提示。比如,“系統當前繁忙,您的訂單已收到,我們正努力爲您處理訂單中,我們會盡快給您發送訂單確認通知……還請見諒”諸如此類的提示信息。

降低數據的一致性

降低數據的一致性一般來說會使用緩存的方式,或是直接就去掉數據。比如,在頁面上不顯示庫存的具體數字,只顯示有還是沒有庫存這兩種狀態。

對於緩存來說,可以有效地降低數據庫的壓力,把數據庫的資源交給更重要的業務,這樣就能讓系統更快速地運行。

對於降級後的系統,不再通過數據庫獲取數據,而是通過緩存獲取數據。在功能降級中,我們一般使用 Cache Aside 模式或是 Read Through 模式。也就是下圖所示的這個策略。


  • 失效:應用程序先從 cache 取數據,如果沒有得到,則從數據庫中取數據,成功後,放到緩存中。
  • 命中:應用程序從 cache 中取數據,取到後返回。
  • 更新:先把數據存到數據庫中,成功後,再讓緩存失效。

Read Through 模式就是在查詢操作中更新緩存,也就是說,當緩存失效的時候(過期或 LRU 換出),Cache Aside 是由調用方負責把數據加載到緩存,而 Read Through 則用緩存服務自己來加載,從而對應用方是透明的。

停止次要的功能

停止次要的功能也是一種非常有用的策略。把一些不重要的功能給暫時停止掉,讓系統釋放出更多的資源來。比如,電商中的搜索功能,用戶的評論功能,等等。等待訪問的峯值過去後,我們再把這些功能給恢復回來。

當然,最好不要停止次要的功能,首先可以限制次要的功能的流量,或是把次要的功能退化成簡單的功能,最後如果量太大了,我們纔會進入停止功能的狀態。

停止功能對用戶會帶來一些用戶體驗的問題,尤其是要停掉一些可能對於用戶來說是非常重要的功能。所以,如果可能,最好給用戶一些補償,比如把用戶切換到一個送積分卡,或是紅包抽獎的網頁上,有限地補償一下用戶。

簡化功能

關於功能的簡化上,上面的下單流程中已經提到過相應的例子了。而且,從緩存中返回數據也是其中一個。這裏再提一個,就是一般來說,一個 API 會有兩個版本,一個版本返回全量數據,另一個版本只返回部分或最小的可用的數據。

舉個例子,對於一篇文章,一個 API 會把商品詳情頁或文章的內容和所有的評論都返回到前端。那麼在降級的情況下,我們就只返回商品信息和文章內容,而不返回用戶評論了,因爲用戶評論會涉及更多的數據庫操作。

所以,這樣可以釋放更多的數據資源。而商品信息或文章信息可以放在緩存中,這樣又能釋放出更多的資源給交易系統這樣的需要更多數據庫資源的業務使用。

降級設計的要點

對於降級,一般來說是要犧牲業務功能或是流程,以及一致性的。所以,我們需要對業務做非常仔細的梳理和分析。我們很難通過不侵入業務的方式來做到功能降級。

在設計降級的時候,需要清楚地定義好降級的關鍵條件,比如,吞吐量過大、響應時間過慢、失敗次數多過,有網絡或是服務故障,等等,然後做好相應的應急預案。這些預案最好是寫成代碼可以快速地自動化或半自動化執行的。

功能降級需要梳理業務的功能,哪些是 must-have 的功能,哪些是 nice-to-have 的功能;哪些是必須要死保的功能,哪些是可以犧牲的功能。而且需要在事前設計好可以簡化的或是用來應急的業務流程。當系統出問題的時候,就需要走簡化應急流程。

降級的時候,需要犧牲掉一致性,或是一些業務流程:對於讀操作來說,使用緩存來解決,對於寫操作來說,需要異步調用來解決。並且,我們需要以流水賬的方式記錄下來,這樣方便對賬,以免漏掉或是和正常的流程混淆。

降級的功能的開關可以是一個系統的配置開關。做成配置時,你需要在要降級的時候推送相應的配置。另一種方式是,在對外服務的 API 上有所區分(方法簽名或是開關參數),這樣可以由上游調用者來驅動。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章