mythmgn(筆者)是此篇舊文的作者, 曾釋出在其他平臺, 從本月開始在部落格園連載自己的技術文章和思考 (覺得 markdown 的支援好用!) . 轉載請註明出處, 謝謝.
歡迎大家左側關注我的公號, 一起在技術領域互動和討論.
一 分散式儲存系統背景
副本是分散式儲存系統中的常見概念:將一定大小的資料按照一定的冗餘策略儲存,以保障系統在區域性故障情況下的可用性。
副本間的冗餘複製方式有多種,比較常用有兩類:
- Pipeline:像個管道,a->b->c,通過管道的方式進行資料的複製。該方式吞吐較高,但有慢節點問題,某一節點出現擁塞,整個過程都會受影響
- 分發:client -> a client ->b client ->c。系統整體吞吐較低,但無慢節點問題
對於冗餘副本數目,本文選擇常見的三副本方案。
分散式儲存系統一般擁有自動恢復副本的功能,在區域性儲存節點出錯時,其他節點(資料副本的主控節點或者client節點,依副本複製協議而定)自動發起副本修復,將該當機儲存節點上的資料副本恢復到其他健康節點上。在少量當機情況下,叢集的副本自動修復策略會正常執行。但依照大規模儲存服務運維經驗,月百分之X的磁碟故障率和月千分之X的交換機故障率有很大的可能性導致一年當中出現幾次機器數目較多的當機。另外,批量升級過程中若出現了升級bug,叢集按照當機處理需要進行副本修復,導致原本正常時間內可以完成的升級時間延長,也容易出現數目較多的當機事件。
二 雪崩效應的產生
在一段時間內數目較多的當機事件有較大可能性誘發系統的大規模副本補全策略。目前的分散式儲存系統的兩個特點導致這個大規模副本補全策略容易讓系統產生雪崩效應:
a. 叢集整體的free空間較小:通常整體<=30%, 區域性機器小於<=20% 甚至10%
b. 應用混布:不同的應用部署在同一臺物理/虛擬機器器上以最大化利用硬體資源
今年火起來的各種網盤、雲盤類服務就是a的典型情況。在各大公司拼個人儲存容量到1T的背後,其實也在拼運營成本、運維成本。現有的雲端儲存大多隻增不減、或者根據資料冷熱程度做資料分級(類似Facebook的資料分級專案)。雲端儲存總量大,但增量相對小,為了減少儲存資源和頻寬資源浪費,新建立的檔案若原有的儲存資料中已有相同的md5或者sha1簽名則當做已有檔案做內部連結,不再進行新檔案的建立。但即使這樣,整體的資料量還是很大。
目前雲端儲存相關業務未有明顯的收入來源,每年卻有數萬每臺的伺服器成本,為運營成本的考慮,後端分散式儲存系統的空閒率很低。而瞬間的批量當機會帶來大量的副本修復,大量的副本修復很有可能繼而打滿原本就接近儲存quota的其他存活機器,繼而讓該機器處於當機或者只讀狀態。如此繼續,整個叢集可能雪崩,系統殘廢。
三 預防雪崩
本節主要討論如何在系統內部的邏輯處理上防止系統整體雪崩的發生。預防的重要性大於事故之後的處理,預測叢集狀態、提前進行優化也成為預防雪崩的一個方向。
下面選取曾經發生過的幾個實際場景與大家分享。
1. 跨機架副本選擇演算法和機器資源、使用者邏輯隔離
某天運維同學發現某叢集幾十臺機器瞬間失聯,負責觸發修復副本的主控節點開始進行瘋狂的副本修復。大量使用者開始反饋叢集變慢,讀寫夯住。
現場應對:
優先解決——副本修復量過大造成的叢集整體受影響。
a. 處理的工程師當機立斷,gdb到程式更改修復副本的條件為副本<2,而非原本的3(replicas_num),讓主控節點這個時候僅修復副本數小於2個的檔案,即保證未丟失的檔案有至少一個冗餘副本,防止只有一個副本的資料因可能再次發生的掛機造成檔案丟失。
b. 緊急解決這批機器失聯問題,發現是交換機問題,a.b.c.d ip網段的c網段機器批量故障。催促網路組儘快修復。
c. 副本修復到>=2之後,Gdb更改檢測副本不足週期,將幾十秒的檢測時間推遲到1天。等待網路組解決交換機問題。
d. 網路恢復,原有的機器重新加入叢集。大量2副本檔案重新變為3副本,部分3副本全丟失檔案找回。
e. 恢復主控節點到正常引數設定狀態,系統開始正常修復。
改進措施:
在改進措施前,先分析下這次事件暴露的系統不足:
1) Master引數不支援熱修正,Gdb線上程式風險過大。
2) 一定數量但局域性的機器故障影響了整體叢集(幾十臺相對一個大叢集仍屬於局域性故障)。如上所述,月千分之幾的故障率總有機會讓你的儲存系統經歷一次交換機故障帶來的叢集影響。
案例分析後的改進措施出爐:
1) Master支援熱修正功能排期提前,儘早支援核心引數的熱修改。
熱修改在上線後的效果可觀,後續規避過數次線上問題。
2) 在選擇資料副本儲存宿主機器的pickup演算法中加入跨交換機(機架位)策略,強制——或者儘量保證——副本選擇時跨機架位。這種演算法底下的副本,至少有1個副本與其他兩個副本處於不同的交換機下(IP a.b.c.d的c段)。該措施同時作用於新的儲存資料副本選擇和副本缺失後的副本補全策略,能在副本宿主選擇上保證系統不會因為交換機的當機而出現資料丟失,進而避免一直處於副本補全佇列/列表的大量的丟失副本節點加重主控節點負載。
3) 機器按region劃分隔離功能提上日程;使用者儲存位置按照region進行邏輯劃分功能提上日程;Pickup演算法加入跨region提上日程。
a) 機器按照物理位置劃分region、使用者按照region進行邏輯儲存位置劃分,能讓叢集在區域性故障的情況下僅影響被邏輯劃分進使用這部分機器的使用者。
這樣一來,最壞情況無非是這個region不可用,導致擁有這個region讀寫許可權的使用者受影響。Pickup演算法跨region的設計進一步保證被劃分region的使用者不會因為一個region不可用而出現資料丟失,因為其他副本存到其他region上了。於是,核心交換機故障導致一個region數百臺機器的當機也不會對叢集造成範圍過大的影響了。
b) 增加region可信度概念,將機器的穩定性因素加入到副本冗餘演算法中。
當叢集規模達到一定量後,會出現機器穩定性不同的問題(一般來說,同一批上線的機器穩定性一致)。通過標記region的穩定性,能強制在選擇資料副本的時候將至少一個副本至於穩定副本中,減少全部副本丟失的概率。
c) Region劃分需要綜合考慮使用者操作響應時間SLA、物理機器穩定情況、地理位置等資訊。
合理的region劃分對提升系統穩定性、提升操作相應時間、預防系統崩潰都有益處。精巧的劃分規則會帶來整體的穩定性提升,但也增加了系統的複雜度。這塊如何取捨,留給讀者朋友深入思考了。
2. 讓叢集流控起來
流控方面有個通用且符合分散式儲存系統特點的原則:任何操作都不應占用過多的處理時間。這裡的“任何操作”包含了在系統出現流量激增、區域性達到一定數量的機器當機時進行的操作。只有平滑且成功的處理這些操作,才能保證系統不因為異常而出現整體受影響,甚至雪崩。
現場還原:
1) 場景1 某天運維同學發現,叢集寫操作在某段時間大增。通過觀察某個儲存節點,發現不僅是寫、而且是隨機寫!某些產品線的整體吞吐下降了。
2) 場景2 某叢集儲存大戶需要進行業務調整,原有的資料做變更,大量資料需要刪除。
運維同學發現,a. 整個叢集整體上處於瘋狂gc垃圾回收階段 b. 叢集響應速度明顯變慢,特別是涉及到meta元資訊更新的操作。
3) 場景3 某天運維同學突然發現叢集併發量激增,單一使用者xyz進行了大量的併發操作,按照原有的使用者調研,該使用者不應該擁有如此規模的使用場景。
此類叢集某些操作預期外的激增還有很多,不再累述。
現場應對:
1) 立刻電聯相關使用者,瞭解操作激增原因,不合理的激增需要立刻處理。
我們發現過如下不合理的激增:
a. 場景1類:通過Review程式碼發現,大量的操作進行了隨機讀寫更改。建議使用者將隨機讀寫轉換為讀取後更改+寫新檔案+刪除舊檔案,轉換隨機讀寫為順序讀寫。
b. 場景3類:某產品線線上上進行了效能測試。運維同學立刻通知該產品線停止了相關操作。所有公有叢集再次發通過郵件強調,不可用於效能測試。如有需要,聯絡相關人員在獨佔叢集進行效能場景測試。
2) 推動設計和實現叢集各個環節的流控機制功能並上線。
改進措施:
1) 使用者操作流控
a. 對使用者操作進行流控限制
可通過系統內部設計實現,也可通過外部的網路限流等方式實現,對單使用者做一定的流控限制,防止單個使用者佔用過多整個叢集的資源。
b. 儲存節點操作流控
可按照對叢集的資源消耗高低分為High – Medium – Low三層,每層實現類似於搶token的設計,每層token數目在叢集實踐後調整為比較適合的值。這樣能防止某類操作過多消耗叢集負載。若某類操作過多消耗負載,其他操作類的請求有較大delay可能,繼而引發timeout後的重試、小範圍的崩潰,有一定機率蔓延到整個叢集併產生整體崩潰。
c. 垃圾回收gc單獨做流控處理。刪除操作在分散式儲存系統裡面常用設計是:接收到使用者刪除操作時,標記刪除內容的meta資訊,直接回返,後續進行策略控制,限流的刪除,防止大量的gc操作消耗過多單機儲存節點的磁碟處理能力。具體的限流策略和token值設定需要根據叢集特點進行實踐並得出較優設定。
2) 流控黑名單
使用者因為對線上做測試類的場景可以通過人為制度約束,但無法避免線上使用者bug導致效果等同於線上測試規模的場景。這類的場景一般在短時間內運算元嚴重超過限流上限。
對此類場景可進行流控黑名單設定,當某使用者短時間內(e.g. 1小時)嚴重超過設定的上限時,將該使用者加入黑名單,暫時阻塞操作。外圍的監控會通知運維組同學緊急處理。
3) 儲存節點併發修復、建立副本流控
大量的資料副本修復操作或者副本建立操作如果不加以速度限制,將佔用儲存節點的頻寬和CPU、記憶體等資源,影響正常的讀寫服務,出現大量的延遲。而大量的延遲可能引發重試,加重叢集的繁忙程度。
同一個資料宿主程式需要限制併發副本修復、副本建立的個數,這樣對入口頻寬的佔用不會過大,程式也不會因為過量進行這類操作而增加大量其他操作的延遲時間。這對於採用分發的副本複製協議的系統尤其重要。分發協議一般都有慢節點檢查機制,副本流控不會進一步加重系統延遲而增大成為慢節點的可能。如果慢節點可能性增大,新建立的檔案可能在建立時就因為慢節點檢查機制而缺少副本,這會讓叢集狀況更加惡化。
3. 提前預測、提前行動
1) 預測磁碟故障,容錯單磁碟錯誤。
場景復現:
某廠商的SSD盤某批次存在問題,叢集上線執行一段時間後,區域性集中出現數量較多的壞盤,但並非所有的盤都損壞。當時並未有單磁碟容錯機制,一塊磁碟壞掉,整個機器就被置成不可用狀態,這樣導致擁有這批壞盤的機器都不可用,叢集在一段時間內都處於副本修復狀態,吞吐受到較大影響。
改進措施:
a) 對硬碟進行健康性預測,自動遷移大概率即將成為壞盤的資料副本
近年來,對磁碟健康狀態進行提前預測的技術越來越成熟,技術上已可以預判磁碟健康程度並在磁碟擁有大概率壞掉前,自動遷移資料到其他磁碟,減少磁碟壞掉對系統穩定性的影響。
b) 對單硬碟錯誤進行容錯處理
儲存節點支援對壞盤的異常處理。單盤掛掉時,自動遷移/修復單盤的原有資料到其他盤,而不是程式整體宕掉,因為一旦整體宕掉,其他盤的資料也會被分散式儲存系統當做缺失副本,儲存資源緊張的叢集經歷一次這樣的當機事件會造成長時間的副本修復過程。在現有的分散式儲存系統中, 也有類似淘寶TFS那樣,每個磁碟啟動一個程式進行管理,整機掛載多少個盤就啟動多少個程式。
2) 根據現有儲存分佈,預測均衡性發展,提前進行負載均衡操作。
這類的策略設計越來越常見。由於分散式儲存叢集掛機後的修復策略使得叢集某些機器總有機率成為熱點機器,我們可以對此類的機器進行熱點預測,提前遷移部分資料到相對負載低的機器。
負載均衡策略和副本選擇策略一樣,需要取捨複雜度和優化程度問題。複雜的均衡策略帶來好的叢集負載,但也因此引入高複雜度、高bug率問題。如何取捨,仍舊是個困擾分散式儲存系統設計者的難題。
四 安全模式
安全模式是專案實踐過程中產生的防分散式儲存系統雪崩大殺器,因此我特別將其單獨列為一節介紹。其基本思路是在一定時間內當機數目超過預期上限則讓叢集進入安全模式,按照策略配置、情況嚴重程度,停止修復副本、停止讀寫,直到停止一切操作(一般策略)。
在沒有機器region概念的系統中,安全模式可以起到很好的保護作用。我過去參與的一個專案經歷的某次大規模當機,由於沒有安全模式,系統進行正常的處理副本修復,生生將原本健康的儲存節點也打到殘廢,進而雪崩,整個叢集都陷入瘋狂副本修復狀態。這種狀態之後的叢集修復過程會因為已發生的副本修復導致的元資訊/實際資料的更改而變的困難重重。 該事件最後結局是資料從冷備資料中恢復了一份,丟失了冷備到故障發生時間的資料。
當然,安全模式並非完美無缺。“一段時間”、“上限”該如何設定、什麼時候停副本修復、什麼時候停讀、什麼時候停寫、是自己恢復還是人工干預恢復到正常狀態、安全模式力度是否要到region級別,這些問題都需要安全模式考慮,而此類的設計一般都和叢集設計的目標使用者息息相關。舉例,如果是低延遲且業務敏感使用者,可能會選擇小規模故障不能影響讀寫,而高延遲、高吞吐叢集就可以接受停讀寫。
五 思考
由於分散式儲存系統的複雜性和篇幅所限,本文僅選擇有限個典型場景進行了分析和討論, 真實的分散式儲存系統遠比這數個案例複雜的多、細節的多。如何平衡叢集異常自動化處理和引入的複雜度,如何較好的實現流控和避免影響低延遲使用者的響應時間,如何引導叢集進行負載均衡和避免因負載均衡帶來的過量叢集資源開銷,這類問題在真實的分散式儲存系統設計中層出不窮。如果設計者是你,你會如何取捨呢?