回顧系列
- 回顧 01:Coinbase re:Invent 回顧 (IND3312)
- 回顧 02:利用 AI 和 AWS 構建未來交易平臺
- 回顧 03:交易創新:Jefferies 在 Amazon Bedrock 上的 AI 助理 (IND3315)
- 回顧 04:FSI 如何運用代理式 AI 徹底改造 HFT 分析 (GBL302)
- 回顧 05:透過 Amazon Time Sync 改善分散式系統,Nasdaq 專題分享
- 回顧 06:Amazon Aurora HA 與 DR 的全球韌性設計模式 (DAT442)
- 回顧 07:建構代理式 AI:Amazon Nova Act 與 Strands Agents 實務應用 (DEV327)
- 回顧 08:深入探討 Amazon Aurora 及其創新 (DAT441)
- 回顧 09:深入探討 Amazon S3 (STG407)
- 回顧 10:Nasdaq:為全球金融服務打造具彈性的基礎設施(HMC327)
- 回顧 11:AWS Lambda 的最新功能 (CNS376)
- 回顧 12:使用 Kiro 進行規格驅動開發 (DEV314)
- 回顧 13:Amazon 的 FinOps:全球電子商務巨擘的雲端成本經驗 (AMZ308)
- 回顧 14:AWS 上的 Tick-to-trade 延遲交易平台
場次筆記
簡介
- 處理故障的伺服器層級策略
- 本系列聚焦於 S3 操作的較低層級詳細資訊
- 今年的焦點:可用性設計
- 方法
- 兩個角度:系統層級及伺服器層級觀點
- 關於故障架構、寫入後讀取一致性、故障實作的系統層級觀點
- 定義術語
- 可用性:處理故障
- 故障:可能發生故障的元件(磁碟機、伺服器、機架、建築物)
- 故障類型:永久遺失或暫時無法使用(電力、網路、過載)
- 設計目標:圍繞目標設計的系統(例如 99.99% 可用性、11 個 9 的耐久性、寫入後讀取一致性)
- S3 的設計目標
- 專為高可用性及耐久性而設計
- 寫入後讀取一致性於 2020 年推出
- 在 2020 年之前,可接受的故障處理包括違反一致性保證
一致性推出前的 S3:處理故障與索引子系統
一致性定義
- 一致性:對某個物件執行 GET 時,結果會反映最近一次對該物件執行的 PUT
- 索引子系統
- 保存物件中繼資料(名稱、標籤、建立時間)
- 每個資料平面請求(GET、PUT、LIST、HEAD、DELETE)都會存取
- 前往索引的請求比前往儲存子系統的更多
- 索引系統的核心:用來持久保存索引項目的專用儲存體 基於 Quorum 的演算法
- 使用基於 Quorum 的演算法將資料儲存在多個複本中
- 可容忍故障
- 伺服器在不同的可用區域(AZ)中執行,以避免故障集中在單一故障域
- 任何單一磁碟、伺服器、機架或可用區域故障,都只會影響一小部分資料 索引中的
- Quorum 實作
- 讀取與寫入都必須觸及多數伺服器
- 範例:寫入值 A 在所有節點上成功
- 寫入值 B:一個節點故障,但 B 在多數伺服器上成功(不影響可用性)
- 讀取端發起讀取:一個伺服器故障,但另外兩個傳回值 B
- 透過關聯的時間戳記解決衝突(B 勝過 A)
- 即使伺服器在請求進行期間故障,讀取與寫入仍會成功
- 系統因有多個節點並容許故障而具備可用性
分散式系統中基於 Quorum 的演算法
概觀
- 基於 Quorum 的演算法會要求最少數量的節點(Quorum)同意讀取或寫入資料等動作,以確保一致性與容錯能力。
- 防止部分節點故障時資料毀損。
關鍵概念
Quorum
- 定義節點總數(N)、寫入 Quorum(W)及讀取 Quorum(R)。
- 讀取操作:
- 讀取請求會傳送至一組節點;若收到 R 個節點的回應,操作便成功。
- 寫入操作:
- 寫入請求會傳送至一組節點;若 W 個節點確認,便提交該寫入。
- 一致性:
- R + W > N 規則可確保任何讀取都會看見最新寫入的資料,因為讀取集合與寫入集合至少必須有一個重疊的節點。
- 容錯能力:
- 若一個節點故障,系統仍可形成 Quorum(例如,五取三系統可容忍 2 個故障)。
範例與應用
資料複寫
- 確保資料的所有副本在叢集中保持一致(例如 Cassandra 等資料庫)。
- 互斥(Maekawa 演算法):
- 節點向其 Quorum 請求存取共用資源(臨界區段)的許可,確保一次只有一個節點進入。
- 共識(Paxos):
- 這是讓分散式系統就單一值達成共識的基礎通訊協定,對領導者選舉與狀態機複寫至關重要。
關鍵參數(URW 模型)
- N:資料副本(節點)總數。
- W:寫入 Quorum(確認寫入所需的節點)。
- R:讀取 Quorum(確認讀取所需的節點)。
S3 基於 Quorum 的系統:確保高可用性與一致性
S3 相容系統中的 Quorum 原則
- 運用 Quorum 原則(多數節點同意)來實現高可用性與一致性
- 適用於叢集或邊緣設定(例如 Snowball Edge 上的 Amazon S3)
在類 S3 系統中的運作方式
分散式共識
- 監控程式或管理程式形成 Quorum(通常為 3 個以上),以追蹤節點運作狀態
- 告知用戶端有哪些可用的儲存節點
- 寫入操作:
- 只有多數(Quorum)儲存節點確認後,寫入才會成功
- 確保整個叢集的資料耐久性與一致性
- 讀取操作:
- 讀取會以複本的 Quorum 為目標,以保證資料為最新狀態
- 容錯能力:
- 總共有 2f+1 個複本時,可容忍 f 個節點故障
- 只要仍有 Quorum,就能選出新的領導者並繼續操作
關鍵範例
Snowball Edge 上的 Amazon S3
- Snowball Edge 裝置叢集使用 Quorum 提供 S3 相容儲存
- 管理裝置狀態與資料可用性 Ceph:
- 搭配 Quorum 使用監控程式與 OSD(Object Storage Daemon)。
- 作為 S3 相容後端,維護叢集狀態與資料可用性。
- Object Storage Daemon(OSD)是 Ceph 等分散式系統中儲存資料的核心程序,充當個別儲存單元,管理本機磁碟(HDD/SSD),並處理大量非結構化資料的複寫、復原及資料分散,因此是可擴展、具彈性的物件儲存之基礎。
- 分散式共識程式庫:
- GitHub 使用 S3 的條件式操作(ETag)進行領導者選舉與 Quorum
- OSD 的關鍵功能:
- 資料儲存:將實際資料物件儲存在本機檔案系統(例如 XFS)上。
- 資料管理:管理整個叢集的資料複寫(建立副本)與復原(重建遺失的資料)。
- 活動訊號監控:檢查其他 OSD 的運作狀態,並向 Ceph Monitor 回報狀態。
- 網路存取:讓用戶端透過網路存取已儲存的資料。
核心 S3 與基於 Quorum 的系統
Amazon S3(核心)
- 在全球基礎設施中原生提供強式寫入後讀取一致性
- 使用者不需明確管理 Quorum 基於 Quorum 的
- S3(叢集/邊緣):
- 在使用者管理的 S3 相容裝置叢集中套用 Quorum 概念
- 確保叢集內部的一致性與可用性
S3 的系統層級可用性設計與快取層
核心概念
- 有多個節點可供路由,並預留故障餘裕
- 經過設定與容量規劃,以達成 99.99% 的可用性目標
- 2020 年以前的寫入後讀取一致性
- 由於讀取與寫入重疊(兩者都必須觸及多數伺服器),讀取端會看到寫入端寫入的值
- 問題:為什麼 S3 在 2020 年以前不具備寫入後讀取一致性?
- 答案:快取層
- 快取層
- S3 的前端會大量快取經常存取的物件
- 不一致的讀取:傳回值 B,而不是 C(最後寫入的值)
- 讀取與寫入不會在快取中重疊
- 快取具有關鍵的可用性特性(多部主機可接收請求,並容許故障)
- 快取中的讀取與寫入沒有重疊
- 由於 2020 年以前的設計目標不包含一致性,這是當時可接受的故障處理方式
- 快取層範例:
- 空的快取節點,儲存體中的值為 B
- 讀取端透過快取節點讀取,傳回值 B 並留存在快取中
- 對 C 的寫入覆寫物件,並持久保存至複本(C C C)
- 值 B 與 C 分別快取在不同節點上(2020 年以前的設計)
- 讀取路由至先前的快取節點,傳回值 B(不一致的讀取)
使用快取一致性通訊協定解決重疊問題
最多人要求的功能:一致性
- 一致性是 2020 年以前最多人要求的功能
- 目標:解決快取層中的重疊問題
- 快取一致性通訊協定
- 必須快速、有效率且具備可用性
- 保留多部伺服器可接收請求,同時容許部分伺服器故障的特性
- 解決方案:複寫式日誌
- 複寫式日誌
- 節點串連在一起的分散式資料結構
- 寫入依序流經節點
- 每個節點都會轉送至下一個節點
- 通過日誌後,寫入會傳送至儲存節點的 Quorum
- 日誌會追蹤近期歷史記錄,並就順序達成共識
- 範例:A 在 B 之前
- 基於 Quorum 的系統無法正確判斷順序
- 日誌為異動建立明確定義的順序
- 序號與水位標記
- 所有寫入都會獲派一個序號(隨時間遞增)
- 範例:A(序號 1)、B(序號 2)、C(序號 3)
- 儲存節點會連同值一起得知序號
- 序號會連同值一起儲存在快取中
- 快取節點可以詢問指定序號之後是否有任何寫入抵達 Witness
- 系統
- 用途:追蹤索引寫入的高水位標記
- Witness 不需要保存實際資料,只需保存序號
- Witness 可以高估最後一個序號(告知呼叫端其資料已過期是安全的)
- 如果呼叫端得知其資料已過期,便會從儲存體讀取並取得正確結果
透過動態重新設定確保故障容許度與一致性
Witness 系統
- 日誌旁的記憶體內資料結構(整數陣列)
- 讓快取節點詢問快取值之後是否有任何寫入傳入
- 修改後的讀寫演算法:
- 寫入會前往日誌
- 讀取會與 Witness 通訊;若沒有問題,便從快取傳回;若已過期,則前往儲存體
- 遺失故障容許度
- 原始日誌架構:若一個節點故障,寫入便無法在系統中繼續進行
- Quorum 服務會並行處理寫入;日誌則依序傳送寫入
- 日誌中的節點故障可能使整個系統停止
- 動態重新設定
- 導入此機制以修正故障容許度問題
- 日誌中的節點會彼此監控可用性
- 持續互相執行 ping;訊息會通過系統
- 節點掌握鄰近節點可用性的最新狀態
- 遇到問題時,節點會要求基於 Quorum 的設定系統重新設定日誌
- 節點故障後幾毫秒內便會完成重新設定
- 設定系統本身也是基於 Quorum
- 結果
- 具備故障容許度且讀取與寫入重疊的快取
- S3 現在同時具備一致性與高可用性
- 在推出一致性功能時,透過將可用性納入設計而保留高可用性
- 全系統可用性觀點
- 需要有許多伺服器可供選擇
- 只需在其中一部分成功
- 面對故障時快速重新設定系統的能力
- 即使在日誌等系統中,也始終存在基於 Quorum 的演算法
在實作層級處理故障
瞭解故障
- 問題:哪些項目可能故障?
- 關聯性故障至關重要:同時發生的故障
- 思考可用性時,關聯性故障不可或缺
- Quorum 設計:可以容許一個節點故障,但若所有節點都位於相同 AZ 或機架中則不行
實體故障
S3 的高階實體檢視
- 多個可用區域(AZ)
- 每個 AZ 都有多個伺服器機架
- 每部伺服器都有多個硬碟
- 實體故障類型:
- 個別故障:硬碟馬達損壞、碟片被刮傷
- 關聯性故障:
- 伺服器故障:所有連接的硬碟都顯示為故障
- 機架故障:機架中的所有磁碟機都故障(例如交換器故障)
- AZ 故障:整個 AZ 停擺(例如停電)
- 邏輯故障
- 範例:將新軟體部署至機群
- 每次部署到少數幾個節點,逐步增加
- 執行新軟體的一組伺服器形成一個故障域
- 若新軟體中有錯誤,所有這些伺服器可能會同時故障
- 需要智慧型部署策略,以容忍潛在故障
因應關聯性故障進行設計
讓工作負載分散至多個故障域
- 跨多個位置(例如 AZ)複寫物件,以實現耐久性與可用性
- 確保即使關聯性故障域(例如 AZ、機架、伺服器)故障,資料仍然可用
瞭解故障類型
故障即停機故障
- 伺服器或元件停止運作(例如電源線被拔除)
- 在具容錯能力的系統中容易偵測並因應 連接
- AZ 的交換器發生故障即停機故障:
- 部分請求仍會繼續成功(位於相同 AZ 內)
- 其他請求開始失敗(通過故障的交換器)
- 導致模糊故障模式,其中部分請求成功,部分則失敗
因應模糊故障模式進行設計
- 備援是關鍵:AZ 之間有多個交換器
- 每個區域中的 3 個 AZ 連接成環狀
- 若一條連線故障(例如 AZ1 至 AZ2),可以繞遠路(AZ1 至 AZ3 至 AZ2)
- 將可用性問題轉換為延遲問題,從而維持可用性
- 強大的思考模型:將一種問題轉換為另一種問題(例如從可用性轉為延遲)
狀態式系統中故障即停機故障的挑戰
狀態式系統中的故障即停機故障
- 在 S3 等系統中很難推理
- 可能導致出現原本無法到達的狀態
- 當機一致性
- 系統在發生故障即停機故障後,應回到一致的狀態
- 範例:將兩行文字寫入檔案
- 正常執行:檔案包含兩行
- 執行期間發生故障即停機故障:檔案可能只有第一行
- 在沒有故障的情況下進入無法到達的狀態
- 因應無法到達的狀態進行設計
- 曾撰寫一篇關於 Shodstor(儲存節點軟體)的論文來處理此問題
- 著重於在故障與並行處理存在時,對可到達狀態進行推理
處理灰色故障
灰色故障
- 比故障即停機更複雜的故障模式
- 範例:
- S3 中的一個 put 請求
- 請求從網際網路傳至 S3 前端伺服器
- 前端伺服器將資料散發至儲存節點
- 灰色故障的定義
- 並非完全故障(例如故障即停機),但會使系統出現非預期行為的故障
- 範例:前端 Web 伺服器接受請求,但因網路問題而無法連線至部分下游主機
- 伺服器針對失敗的請求傳回錯誤,但仍繼續接受請求並回應
- 使用重試處理灰色故障
- 強大的技巧:若請求失敗,改用不同路徑重試(例如不同的前端 Web 伺服器)
- AWS SDK 具備精密的重試策略,會刻意在不同的 IP 位址上重試請求
- 重試可嘗試透過系統的不同路徑
- 分散式系統中重試的危險
- 若所有服務都重試失敗的請求,重試可能會導致工作量大幅放大
- 範例:堆疊底層的故障可能導致重試次數是原始請求的 27 倍
- 過多的重試可能使系統超載
- 刻意設計重試策略
- 設計重試策略時必須審慎,以避免系統超載
- 範例:堆疊越往下層,重試次數越少或不重試,因為已知更上層會進行重試
- 在保護系統免於過多重試的同時確保可用性
- 負載造成的灰色故障
- Web 伺服器因工作超載,表現為請求緩慢
- 強大的機制:逾時(用戶端讓緩慢的請求逾時,並在其他位置重試)
- 逾時的挑戰
- 逾時並不完美,也很難因應其進行設計,尤其是與重試搭配時
- 範例:
- 具有請求佇列且超載的 Web 伺服器
- 用戶端逾時並在其他位置重試
- 伺服器仍繼續處理已逾時的請求,不知道用戶端已重試
- 導致伺服器對用戶端已放棄的請求執行無用工作
- 壅塞崩潰
- 伺服器只處理已逾時並在其他位置重試之請求的狀態
- 連鎖反應:超載的伺服器變得更慢,造成更多重試與佇列堆積
- 伺服器將所有時間都花在處理由重試造成之失敗逾時的自我強化循環
- 因應措施:反向佇列處理
- 處理佇列已滿之超載伺服器的機制
- 從佇列尾端開始處理(後進先出)
- 雖然不公平,但會讓部分用戶端付出代價,使其他用戶端變得非常快速
自我修復系統設計
擺脫壅塞崩潰
- 反向佇列處理:從佇列尾端開始處理(後進先出)
- 讓部分請求成功,減少已逾時之緩慢請求的積壓
- 退避與重試:用戶端進行退避,並以較慢的速度重試
- 給予伺服器時間處理完積壓工作
- 亞穩態故障模式
- 即使原始問題已解決,系統仍將所有時間花在處理已逾時請求的狀態
- 系統層級故障復原
- 目標:S3 應在無需人工介入的情況下自行修復
- 範例:Web 伺服器未成功回應請求
- 用戶端在其他位置重試,但該伺服器需要停止服務
- 運作狀態檢查
- 用於自動修復伺服器的重要工具
- 運作狀態檢查伺服器會向 Web 伺服器傳送請求,以檢查功能是否正常
- 若伺服器未通過運作狀態檢查,可將其停止服務(例如從 DNS 移除)
- 防止用戶端連線至故障伺服器,藉此減輕故障
- S3 對 AWS 基礎設施的使用
- S3 建置在 AWS 上,使用與客戶可用的相同基礎設施
- Web 伺服器容量:Network Load Balancer
- DNS:Route 53
- 使用 NLB 與 Route 53 實作運作狀態檢查
確保健全的運作狀態檢查與系統運作狀態全域檢視
單一運作狀態檢查的危險
- 運作狀態檢查伺服器可能故障,導致錯誤偵測 Web 伺服器故障
- 範例:發生網路問題的運作狀態檢查伺服器將所有 Web 伺服器標示為異常
- 必須同時考量伺服器與運作狀態檢查系統的可用性進行設計
- 運作狀態檢查的多重觀點
- S3 使用來自多個來源的運作狀態檢查:
- 相同區域
- 不同區域
- 公共網際網路
- 結合訊號以形成 Web 伺服器運作狀態的詳細檢視
- 協助診斷關聯性故障(例如網路問題)
- 避免區域性決策
- 重要原則:絕不讓區域系統針對服務運作狀態做出區域性決策
- 範例:原始運作狀態檢查根據自身的系統檢視做出區域性決策
- 分散式系統需要全域檢視,以避免區域性決策造成錯誤
- 系統運作狀態全域檢視
- 範例:偵測並修復故障的硬碟
- 軟體偵測到故障的硬碟
- 觸發修復(例如重新啟動電源、由技術人員更換)
- 運作狀態檢查的全域速率限制器
- 運作狀態檢查服務在變更系統前,必須查詢全域速率限制器
- 範例:運作狀態檢查偵測到故障的硬碟,並想讓它停止服務
- 若運作狀態檢查服務失控,速率限制器會阻止移除過多硬碟
- 可用性設計回顧
- 定義可用性與正確性目標
- 設計整體系統架構以符合目標(例如基於 Quorum 的架構、強式一致性)
- 瞭解故障模式並在不做區域性決策的情況下進行修復,以實作系統各部分
