無服務器場景(serverless)的容錯怎麼做?我們的設計

無服務器架構和FaaS(Function-as-a-service 函數即服務)近年來越來越受歡迎,這要歸功於易用性、自動伸縮和按需付費的特性。然而,FaaS 基礎設施中缺少應用程序的容錯能力。

把坑留給碼農?

默認情況下,AWS Lambda 或 Google Cloud Functions 等 FaaS 系統需要開發者自己考慮執行失敗的情況。雲服務的策略是:無論是應用程序自身錯誤還是基礎設施故障,一旦函數執行失敗就執行重試。這意味著函數可能會運行多次。

並且更可怕還有,你的業務代碼也可能會運行 0.5 次,或者 3.2 次……這是怎麼回事?

這個糟糕問題的原因是,大多數 FaaS 系統提供的能力不能保證資源層(如數據庫或文件等)在執行失敗後被清理。

在失敗和重試的過程中,修改共享狀態的應用程序會在不知不覺修改部分結果。如果一個請求將更新兩個鍵 k 和 l,但函數在兩次更新之間崩潰,那麼現在客戶端將看到較新版本的 k 和較舊版本的 l。

這就是雲平臺 FaaS 的現狀。

FaaS 的無痛容錯:原子性

為了避免這種類型的異常,開發人員需要一個簡單的保證,那就是原子性:要麼一個請求的所有操作全部成功,要麼全部失敗。傳統做法中,原子性是由強一致性(事務式)存儲引擎來保證的,但這些系統有眾所周知的擴展和性能問題。如何才能讓 FaaS 執行保證原子性?

為此,我們構建了一個名為 AFT(Atomicity for Fault Tolerance)的系統,它是一個位於任何無服務器計算層(如AWS Lambda、Google Cloud Functions)和存儲層(如AWS DynamoDB、Redis)之間的膠合層。計算層的每個邏輯請求(可能由多個函數組成)都被視為一個事務。AFT 保證事務所做的所有更新都會在存儲層原子化執行。

AFT 的設計是靈活的。我們對計算層不做任何假設,而對存儲層的要求就是存儲層要持久化。我們可以保證在 DynamoDB 和 S3 等最終一致的系統上運行的函數的原子性。AFT 有兩個主要特點。(1)無協調、原子更新;(2)保證事務只讀取已提交的數據。AFT 將每個新的key版本寫到不同的物理存儲位置,以避免寫-寫衝突。

為了保證事務讀取語義上一致的數據,AFT 保證了讀取原子性。讀取原子性要求客戶機只從已提交的事務中讀取數據,並按照事務提交的順序進行讀取。也就是說,如果事務 T1 寫了 key 的版本 K1,而後來的事務 T2 寫了 K2 和 L2,那麼客戶端就讀不到 K1 和 L2,因為事務 T2 寫了一個較新版本的K,稱為 K2。所有這些都可以在沒有任何協調¹的情況下完成。這種類型的異常被稱為斷裂讀。

無服務器場景(serverless)的容錯怎麼做?我們的設計
無服務器場景(serverless)的容錯怎麼做?我們的設計

下一步

我們對膠合層架構作為探索不同開發者保障的手段感到興奮。特別是有一整類應用可以從無服務器架構中受益,但需要找到將更強的一致性引入 Faas 世界的方法。

熟悉數據庫內部的朋友可能已經注意到,我們這裡講到的讀取原子性保證類似於無協調版本的快照隔離,這是傳統數據庫中常用的強一致性形式。我們正計劃在此背景下探索如何將強一致性引入到無服務器應用中。如果你對這些有興趣可以通過原文鏈接反饋給我們。

原文地址:

https://medium.com/riselab/solving-serverless-computings-fault-tolerance-problem-122128fa5787

完整論文鏈接:

[1] https://arxiv.org/pdf/2003.06007.pdf

本文由高可用架構翻譯。技術原創及架構實踐文章,歡迎通過公眾號菜單「聯繫我們」進行投稿。

高可用架構

改變互聯網的構建方式


分享到:


相關文章: