分布式學習最佳實踐:從分布式系統的特征開始(附思維導圖)


   

我的探索歷程

  這一部分,與分布式不大相關,記錄的是我是如何在分布式學習這條道路上摸索的,不感興趣的讀者請直接跳到下一章

  過去的一年,我在分布式學習這條道路上苦苦徘徊,始終沒有找到一個好的學習方法,一個能激勵我持續學習的方法。

  當然,我也在不停的反思,最先發現的問題是學習不系統,東看看,西看看,看過就忘。於是寫了一篇文章《帶着問題學習分布式系統》提出了一些問題,然后寫了兩篇文章來回帶自己提出的問題。回過頭看,其實這兩篇文章都是基於分布式存儲的。

  然后接下來,又是一段時間的迷茫,不知道要學習啥(也是在學習Paxos的時候遇到了阻礙),偶然看到了關於SMART的一些文章,發現原來自己的學習一點都不SAMRT,所以堅持不下去。於是又寫了一篇文章《帶着SMART原則重新出發》,希望給自己設定SMART的目標,結果被博友打臉“一點都不smart”,而且也被結果打臉了,確實沒有讓我“重新出發”。

  我也曾經在網上搜索,“如何學習分布式系統“,但並沒有找到理想的、或者說適合我的學習方法。網上的答案,都是說,看這些論文,看這些系統的實現。。。或者很多大學的課程,都是羅列出一堆術語:概念、協議、組件。而我覺得,逐個去了解這些術語似乎很無聊,因為不知道為什么要這個協議,或者說這些協議、組件是如何組合起來的。

  在沒有得到適合自己的方案之后,我自己思考,希望更系統、全面的掌握,於是寫了這篇文章《什么是分布式系統,如何學習分布式系統》。主要內容是,從一個實際的大型網絡出發,思考會遇到哪些問題,需要哪些分布式協議與組件。寫完這篇文章,我的想法就是,逐個去學習這些組件。

  春節的時候,看完了《小強升職記》,里面寫到要用六個高度與大樹分解法來設定自己的目標,制定自己的執行計划。於是,我嘗試用這兩個方法來指導我對分布式的學習。遺憾的是,在大數據分解法 樹干(月計划)這一層,我就無法計划下去了,不知道每個月要學啥。具體原因,我想,還是沒有一個對分布式系統的整理的認識。怎么整體把握呢,我想起了之前看到過的思維導圖,於是就想畫一張分布式系統的思維導圖,然后逐個擊破。當然,最開始也是瞎畫,當時划出了5個樹干,是這樣子的:

        

  在延伸feature(分布式系統需要考慮的特性)的時候,我逐漸明白,這是因為要滿足這些feature,才設計了很多協議與算法,也提出了一些理論。比如說,這是因為要解決去中心化副本的一致性問題,才引入了Paxos(raft)協議。而每一個分布式系統,如分布式存儲、分布式計算、分布式消息隊列、分布式RPC框架,根據業務的不同,會使用不同的方法來滿足這些feature,對這些feature的支持也可能會有權衡,比如一致性與可用性的權衡。

  所有,我覺得從分布式的特性出發,來一步步學習分布式是一種可行的方式。

從分布式系統的特征出發

  分布式的世界中涉及到大量的協議(raft、2pc、lease、quorum等)、大量的理論(FLP, CAP等)、大量的系統(GFS、MongoDB、MapReduce、Spark、RabbitMQ等)。這些大量的知識總是讓我們無從下手,任何一個東西都需要花費大量的時間,特別是在沒有項目、任務驅動的時候,沒有一個明確的目標,真的很難堅持下去。

  所以,我一直在思考,能有什么辦法能把這些東西串起來?當我掌握了知識點A的時候,能夠自然地想到接下來要學習B知識,A和B的關系,也許是遞進的,也許是並列的。我也這樣嘗試了,那就是《什么是分布式系統,如何學習分布式系統》一文中我提到的,思考一個大型網站的架構,然后把這些協議、理論串起來。按照這個想法,我的計划就是去逐個學習這些組件。

  但是,其實在這里有一個誤區,我認為一個大型網站就是一個分布式系統,包含諸多組件,這些組件是分布式系統的組成部分;而我現在認為,一個大型網站包含諸多組件,每一個組件都是一個分布式系統,比如分布式存儲就是一個分布式系統,消息隊列就是一個分布式系統。

 

  為什么說從思考分布式的特征出發,是一個可行的、系統的、循序漸進的學習方式呢,因為:

  (1)先有問題,才會去思考解決問題的辦法

  由於我們要提高可用性,所以我們才需要冗余;由於需要擴展性,所以我們才需要分片

  (2)解決一個問題,常常會引入新的問題

  比如,為了提高可用性,引入了冗余;而冗余又帶來了副本之間的一致性問題,所以引入了中心化副本協議(primary/secondary);那么接下來就要考慮primary(節點)故障時候的選舉問題。。。

  (3)這是一個金字塔結構,或者說,也是一個深度優先遍歷的過程。

  在這個過程中,我們始終知道自己已經掌握了哪些知識;還有哪些是已經知道,但未了解的知識;也能知道,哪些是空白,即我們知道這里可能有很多問題,但是具體是什么,還不知道。

  

  那么,各個分布式系統如何與這些特征相關聯呢?不難發現,每個分布式系統都會或多或少的體現出這些特征,只是使用的方法、算法可能不大一樣。所以,我們應該思考,某一個問題,在某個特定系統中是如何解決的。比如元數據管理的強一致性,在MongoDB中是如何實現的,在HDFS中是如何實現的。這也指導了我們如何去學習一個具體的分布式系統:帶着問題,只關注關心的部分,而不是從頭到尾看一遍。

  下面是,到目前為止,我對分布式特征的思維導圖

   

  對於上圖,需要聲明的是,第一:不一定完全正確,第二:不完整。這是因為,我自己也在學習中,可以看到,很多分支很短(比如去中心化副本協議),不是因為這一塊沒有內容,而是我壓根兒還沒去了解,還沒去學習。

  我會持續跟新這幅腦圖的

  

  下一章,介紹一下分布式系統的各個特征。

分布式系統的一般特征

   任何介紹分布式系統的文章或者書籍都會提到分布式系統的幾個特性:可擴展性、高性能、高可用、一致性。這幾個特性也是分布式系統的衡量指標,正是為了在不同的程度上滿足這些特性(或者說達到這些指標),才會設計出各種各樣的算法、協議,然后根據業務的需求在這些特性間平衡。

  那么本章節簡單說明,為什么要滿足這些特性,要滿足這些特性需要解決什么問題,有什么好的解決方案。

可擴展性

  

Scalability is the capability of a system, network, or process to handle a growing amount of work, or its potential to be enlarged to accommodate that growth.

  可擴展性是指當系統的任務(work)增加的時候,通過增加資源來應對任務增長的能力。可擴展性是任何分布式系統必備的特性,這是由分布式系統的概念決定的:

分布式系統是由一組通過網絡進行通信、為了完成共同的任務而協調工作的計算機節點組成的系統

  分布式系統的出現是為了解決單個計算機無法完成的計算、存儲任務。那么當任務規模增加的時候,必然就需要添加更多的節點,這就是可擴展性。

  擴展性的目標是使得系統中的節點都在一個較為穩定的負載下工作,這就是負載均衡,當然,在動態增加節點的時候,需要進行任務(可能是計算,可能是數據存儲)的遷移,以達到動態均衡。

  那么首先要考慮的問題就是,如何對任務進行拆分,將任務的子集分配到每一個節點,我們稱這個過程問題Partition(Sharding)。關於Partition,其實我在《帶着問題學習分布式系統之數據分片 》一文中有詳細介紹,這里進行歸納總結。

第一:分片分式,即按照什么算法對任務進行拆分

  常見的算法包括:哈希(hash),一致性哈希(consistency hash),基於數據范圍(range based)。每一種算法有各自的優缺點,也就有各自的適用場景。

第二:分片的鍵,partition key

  partition key是數據的特征值,上面提到的任何分片方式都依賴於這個partition key,那么該如何選擇呢

 based on what you think the primary access pattern will be

  partition key會影響到任務在分片之間的均衡,而且一些系統中(mongodb)幾乎是不能重新選擇partition key的,因此在設計的時候就得想清楚

第三:分片的額外好處

  提升性能和並發:不同的請求分發到不同的分片

  提高可用性:一個分片掛了不影響其他的分片

第四:分片帶來的問題

  如果一個操作需要跨越多個分片,那么效率就會很低下,比如數據中的join操作

第五:元數據管理

  元數據記錄了分片與節點的映射關系、節點狀態等核心信息,分布式系統中,有專門的節點(節點集群)來管理元數據,我們稱之為元數據服務器。元數據服務器有以下特點:

  高性能:cache

  高可用:冗余 加 快速failover

  強一致性(同時只有一個節點對外提供服務)

第六:任務的動態均衡

  為了達到動態均衡,需要進行數據的遷移,如何保證在遷移的過程中保持對外提供服務,這也是一個需要精心設計的復雜問題。

可用性

  

  可用性(Availability)是系統不間斷對外提供服務的能力,可用性是一個度的問題,最高目標就是7 * 24,即永遠在線。但事實上做不到的,一般是用幾個9來衡量系統的可用性,如下如所示:

  

  也就是如果要達到4個9的可用度(99.99%),那么一年之中只能有52.6分鍾不可用,這是個巨大的挑戰

 

  為什么分布式系統中必須要考慮可用性呢,這是因為分布式系統中故障的概率很高。分布式系統由大量異構的節點和網絡組成,節點可能會crash、斷電、磁盤損壞,網絡可能丟包、延遲、網絡分割。系統的規模放大了出故障的概率,因此分布式系統中,故障是常態。那么分布式系統的其中一個設計目標就是容錯,在部分故障的情況下仍然對外提供服務,這就是可用性。

  冗余是提高可用性、可靠性的法寶

  冗余就是說多個節點負責相同的任務,在需要狀態維護的場景,比如分布式存儲中使用非常廣泛。在分布式計算,如MapReduce中,當一個worker運行異常緩慢時,master會將這個worker上的任務重新調度到其它worker,以提高系統的吞吐,這也算一種冗余。但存儲的冗余相比計算而言要復雜許多,因此主要考慮存儲的冗余。

  維護同一份數據的多個節點稱之為多個副本。我們考慮一個問題,當向這個副本集寫入數據的時候,怎么保證並發情況下數據的一致性,是否有一個節點有決定更新的順序,這就是中心化、去中心話副本協議的區別。

中心化與去中心化

  中心化就是有一個主節點(primary master)負責調度數據的更新,其優點是協議簡單,將並發操作轉變為順序操作,缺點是primar可能成為瓶頸,且在primary故障的時候重新選舉會有一段時間的不可用。

  去中心化就是所有節點地位平等,都能夠發起數據的更新,優點是高可用,缺點是協議復雜,要保證一致性很難。

  提到去中心化,比較有名的是dynamo,cassandra,使用了quorum、vector clock等算法來盡量保證去中心化環境下的一致性。對於去中心化這一塊,目前還沒怎么學習,所以下面主要討論中心化副本集。對於中心化副本協議,我在《帶着問題學習分布式之中心化復制集》一文中也有詳細介紹,這里簡單歸納總結。

節點更新策略

  primary節點到secondary節點的數據時同步還是異步,即客戶端是否需要等待數據落地到副本集中的所有節點。

  同步的優點在於強一致性,但是可用性和性能(響應延遲)比較差;異步則相反。

數據流向

  即數據是如何從Primary節點到secondary節點的,有鏈式和主從模式。

  鏈式的優點時充分利用網絡帶寬,減輕primary壓力,但缺點是寫入延遲會大一些。GFS,MongoDB(默認情況下)都是鏈式。

部分節點寫入異常

  理論上,副本集中的多個節點的數據應該保持一致,因此多個數據的寫入理論上應該是一個事務:要么都發生,要么都不發生。但是分布式事務(如2pc)是一個復雜的、低效的過程,因此副本集的更新一般都是best effort 1pc,如果失敗,則重試,或者告訴應用自行處理。

primary的選舉

  在中心化副本協議中,primary節點是如何選舉出來的,當primary節點掛掉之后,又是如何選擇出新的primary節點呢,有兩種方式:自治系統,依賴其他組件的系統。(ps,這兩個名字是我杜撰的 。。。)

  所謂的自治系統,就是節點內部自行投票選擇,比如mongodb,tfs,zookeeper

  依賴其他組件的系統,是指primary由副本集之后的組件來任命,比如GFS中的primary由master(GFS的元數據服務器)任命,hdfs的元數據namenode由zookeeper心跳選出。

secondary是否對外提供服務(讀服務)

   中心化復制集中,secondary是否對外提供讀服務,取決於系統對一致性的要求。

  比如前面介紹到節點更新策略時,可能是異步的,那么secondary上的數據相比primary會有一定延遲,從secondary上讀數據的話無法滿足強一致性要求。

  比如元數據,需要強一致性保證,所以一般都只會從primary讀數據。而且,一般稱主節點為active(master),從節點為standby(slave)。在這種情況下,是通過冗余 加上 快速的failover來保證可用性。

一致性

  

  從上面可以看到,為了高可用性,引入了冗余(副本)機制,而副本機制就帶來了一致性問題。當然,如果沒有冗余機制,或者不是數據(狀態)的冗余,那么不會出現一致性問題,比如MapReduce。

  一致性與可用性在分布式系統中的關系,已經有足夠的研究,形成了CAP理論。CAP理論就是說分布式數據存儲,最多只能同時滿足一致性(C,Consistency)、可用性(A, Availability)、分區容錯性(P,Partition Tolerance)中的兩者。但一致性和可用性都是一個度的問題,是0到1,而不是只有0和1兩個極端。詳細可以參考之前的文章《CAP理論與MongoDB一致性、可用性的一些思考

  一致性從系統的角度和用戶的角度有不同的等級。

系統角度的一致性

   強一致性、若一致性、最終一致性

用戶角度的一致性

   單調讀一致性,單調寫一致性,讀后寫一致性,寫后讀一致性

高性能

  

   正式因為單個節點的scale up不能完成任務,因此我們才需要scale out,用大量的節點來完成任務,分布式系統的理想目標是任務與節點按一定的比例線性增長。

衡量指標

  高並發

  高吞吐

  低延遲

  不同的系統關注的核心指標不一樣,比如MapReduce,本身就是離線計算,無需低延遲

可行的辦法

  單個節點的scaleup

  分片(partition)

  緩存:比如元數據

     短事務

references

 Distributed systems for fun and profit  

劉傑:《分布式系統原理介紹

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM