1. 程式人生 > >分散式系統設計理念

分散式系統設計理念

首先,分散式系統的首要目的是提升系統的整體效能和吞吐量。如果最終設計出來的分散式系統佔用了10臺機器才勉強達到單機系統的兩倍效能,那麼這個分散式系統還有存在的價值嗎?另外,即使採用了分散式架構,也仍然需要盡力提升單機上的程式效能,使得整體效能達到最高。所以,我們仍然需要掌握高效能單機程式的設計和程式設計技巧,例如多執行緒程式設計、多程序高效能IPC通訊、高效能的網路框架等。

其次,任何分散式系統都存在讓人無法迴避的風險和嚴重問題,即系統發生故障的概率大大增加:小到一個伺服器的硬碟發生故障或宕機、一根網線被老鼠啃壞了,大到交換機甚至幾十臺伺服器一起歇火。在分散式系統下故障概率之所以增加,除了主要由於網路通訊天生的不可靠性及物理上的分佈部署,還由於X86伺服器的品質越來越差,遠不如UNIX小機器,這大概是工業化導致“工匠精神”的匱乏在IT上的一個縮影吧。

綜上分析,我們看到分散式系統社二級的兩大關鍵目標是“效能”與“容錯性”,而這兩個目標的實現恰恰都是很棘手的問題,而且相互羈絆!舉個例子,比如我們設計一個分散式儲存系統,處於對效能的考慮,寫檔案時先寫一個副本到某個機器上並立即返回,然後非同步發起多副本的複製過程,這種設計效能最好,但存在“容錯性”的風險,即檔案寫完後,目標機器立即發生故障,導致檔案丟失!如果同時寫多個副本,每個副本成功以後再返回,則又導致“效能”下降,因為這個過程取決於最慢的那臺機器的效能。

由於“效能”的指標是絕對的,而“容錯性”的指標是絕對的,而且實際上對於不同的資料與業務,我們要求的容錯性其實可以存在很大的差異:允許意外丟失一些日誌類的資料;允許一些資訊類的資料暫時不一致而最終達到一致;而對交易類的資料則要求有很高的可靠性。於是你會發現,很多分散式系統的設計都提供了多種容錯性策略,以適應不同的業務場景,我們在學習和設計分散式系統的過程中也需要注意這一特性。

分散式系統設計中的兩大思路:中心化和去中心化。

中心化

中心化的設計思想很簡單,分散式叢集中的節點機器按照角色分工,大體上分為兩種角色:”領導“和”幹活兒的“,”領導“通常負責分發任務並監督”幹活的“,發現誰太閒,就想方設法地給其安排新任務,確保沒有一個”幹活的“能夠偷懶;如果”領導“發現某個”幹活的“因為勞累過度而病倒了,則是不會考慮先嚐試”醫治“他的,而是一腳踢出去,然後把他的任務分給其他人。而Google最近開源的基於容器技術的微服務架構Kubernetes就恰好採用了這一設計思路。

在分散式中心化的設計思想中,除了上訴的設計思路之外,還有一種設計思路與程式設計中的敏捷開發的做法類似,即充分相信每個“幹活兒的”,“領導”只負責任務的生成而不在指派任務,由每個“幹活的”自發去領任務,從而避免讓個別員工積勞成疾,並鼓勵能者多勞,但還是不發獎金。

中心化的設計存在的最大問題就是“領導”的安危問題,如果“領導”出了問題,則群龍無首,整個系統叢集就會奔潰。但我們難以同時安排兩個“領導”以避免單點問題,是因為“一山不容二虎”。為了解決這個問題,大多數中心化系統都採用了主備兩個“領導”的設計方案,可以是熱備或者冷備,也可以是自動切換或者手動切換,而且越來越多的新系統都開始具備自動選舉切換“領導”的能力,以提升系統的可用性。中心化設計還存在另外一個潛在的問題就是“領導”的能力問題:可以領導10個人高效工作並不意味著可以領導100個人高效工作,所以如果系統設計和實現得不好,問題就會卡在“領導”身上。

去中心化

在去中心化的設計裡,通常沒有“領導”和“幹活兒的”這兩種角色的區分,大家的角色都是一樣的,地位是平等的。去中心化設計的核心在於整個分散式系統中不存在區別於其他節點的“領導”,因此不存在單點故障問題,但由於不存在“領導”,所以每個節點都需要跟其他節點對話才能獲取到必要的資訊,而分散式系統通訊的不可靠性,則大大增加了上訴功能的實現難度。

去中心化最難解決的問題就是“腦裂”問題,這種情況的發生率很低,但影響很大。腦裂指一個叢集由於網路的故障,被分為至少兩個彼此無法通訊的單獨叢集,此時如果兩個叢集都各自工作,則可能會產生嚴重的資料衝突和錯誤。一般的設計思路是,當叢集判斷髮生了腦裂問題,規模較小的叢集就“自殺”或者拒絕服務。

實際上,完全意義的真正去中心化的分散式系統並不多見。相反,外部看來去中心化但工作機制採用了中心化設計思想的分散式系統正在不斷湧出。在這種架構下,叢集中的領導是被動態選擇出來的,而不是人為預先指定的,而且叢集發生故障的情況下,叢集的成員會自發地舉行“會議”選舉新的“領導”主持工作。最典型的案例就是Zookeeper。

參考:架構解密從分散式到微服務(Leaderus著)