來源:html
https://www.zhihu.com/question/23645117/answer/124708083git
個人 PhD 研究方向是分佈式系統,我老闆也是分佈式系統出身,咱們實驗室在這方面的積累還算不錯,因此藉此問題談談本身的見解。首先須要說明的是,分佈式系統是一個複雜且寬泛的研究領域,學習一兩門在線課程,看一兩本書可能都是不能徹底覆蓋其全部內容的。介於這篇文章是引導初學者入門,因此我我的以爲爲初學者介紹一下當前分佈式系統領域的全貌,也許比直接推薦論文和課程更有幫助。當初學者對這個領域創建起一個大的 Picture 以後,能夠根據本身的興趣,有選擇性地深刻不一樣領域進行進一步的學習。github
本文主要試圖回答如下兩個問題:算法
1. 近些年分佈式系統領域都在作些什麼。
2. 爲何如今投入分佈式系統的學習和研究是值得的。數據庫
我會盡量多地去介紹更 「實用」 的分佈式系統知識。編程
什麼是實用?例如:後端
Paxos 是分佈式系統裏一個重要並且實用的技術。服務器
Consistent Hash 也是分佈式系統裏一個重要並且實用的技術。網絡
MapReduce、Spark 等等都是很實用的系統。session
什麼不實用? 例如:
Paxos 算法的數學證實。(注意此處「不實用」 和 「不重要」的區別)
固然,分佈式系統實在是一個太寬泛的話題,本人才疏學淺,回答也僅僅可能側重於我所關心的領域和方向,不少地方都不能面面俱到。因此在此只能拋磚引玉, 走馬觀花,歡迎你們提出寶貴意見,我也會及時對文章進行修改和補充。
分佈式系統近些年都在作些什麼?
分佈式系統是一個古老而寬泛的話題,而近幾年由於 「大數據」 概念的興起,又煥發出了新的青春與活力。除此以外,分佈式系統也是一門理論模型與工程技法並重的學科內容。相較於機器學習這樣的研究方向,學習分佈式系統的同窗每每會感受:「入門容易,深刻難」。
的確,學習分佈式系統幾乎不須要太多數學知識(相比於機器學習),這也是爲何會形成 「入門容易」 的錯覺。然而一旦深刻下去,每每須要咱們去體會 System 研究的 「簡潔」 與 「美」,正如李沐的回答中說的那樣,系統工做是 「藝術」 而不是 「科學」 ,這一點我以爲是系統研究工做最難,同時也是最精華的地方。總之把握一點原則:好的系統研究工做,尤爲是分佈式系統研究,必定是儘量地用最簡單、最直觀的方法去解決實際的問題(看看 MapReduce 就知道了),由於簡單就意味着實用。
整體來講,分佈式系統要作的任務就是把多臺機器有機地組合、鏈接起來,讓其協同完成一件任務,能夠是計算任務,也能夠是存儲任務。若是必定要給近些年的分佈式系統研究作一個分類的話,我我的認爲大概能夠包括三大部分:
1. 分佈式存儲系統
2. 分佈式計算系統
3. 分佈式管理系統
近十年來在這三個方向上,毫無疑問, Google 都是開創者,甚至不少業內人士都說,這十年是外界追隨谷歌技術的十年。咱們以前說到,分佈式系統的研究是一門由實際問題驅動的研究,而 Google 則是最早須要面對這些實際問題的公司。下面咱們分別看看這三個方面工業界以及學術界這幾年都在作些什麼。
分佈式存儲系統:
分佈式存儲系統是一個很是古老的話題,同時也是分佈式系統裏最難,最複雜,涉及面最廣的問題。 往細了分,分佈式存儲系統大概能夠分爲四個子方向:
1. 結構化存儲
2. 非結構化存儲
3. 半結構化存儲
4. In-memory 存儲
除了這四個子方向以外,分佈式存儲系統還有一系列的理論、算法、技術做爲支撐:例如 Paxos、CAP、ConsistentHash、Timing(時鐘)、2PC、3PC 等等,這些內容咱們會在後面提到。如今,咱們先來看看上述四個子方向大體都在幹些什麼。
結構化存儲(Structured Storage Systems)的歷史很是古老,典型的場景就是事務處理系統或者關係型數據庫(RDBMS)。傳統的結構化存儲都是從單機作起的,好比你們耳熟能詳的 MySQL。有句話說:MySQL 的成長史就是互聯網的成長史。這一點也不爲過。除了 MySQL 以外,PostgreSQL 也是近幾年來勢頭很是強勁的一個 RDBMS。咱們發現,傳統的結構化存儲系統強調的是:(1)結構化的數據(例如關係表);(2)強一致性 (例如,銀行系統、電商系統等場景);(3)隨機訪問(索引、增刪查改、SQL 語言)。然而,正是因爲這些性質和限制,結構化存儲系統的可擴展性一般都不是很好,這在必定程度上限制告終構化存儲在大數據環境下的表現。隨着摩爾定律面臨的瓶頸,傳統的單機關係型數據庫系統面臨着巨大的挑戰。不過真的沒辦法了嗎?在此咱們先埋下一個伏筆:)
非結構化存儲 (No-structed Storage Systems):和結構化存儲不一樣的是,非結構化存儲強調的是高可擴展性,典型的系統就是分佈式文件系統。分佈式文件系統也是一個古老的研究話題,好比 70 年代的 Xerox Alto、80 年代的 NFS、AFS、90 年代 xFS 等等。然而,這些早期的分佈式文件系統只是起到了網絡磁盤的做用,其最大的問題就是不支持容錯 (Fault Tolerance)和錯誤恢復 (Fault Recovery)。而 Google 在 2003 年 SOSP 上推出的 GFS(Google File System)則是作出了里程碑的一步,其開源實現對應爲 HDFS。GFS 的主要思想包括:
(1)用 Master 來管理 Metadata。
(2)文件使用 64MB 的 Chunks 來存儲,而且在不一樣的 Server 上保存多個副本。
(3)自動容錯,自動錯誤恢復。
Google 設計 GFS 最初的目的是爲了存儲海量的日誌文件以及網頁等文本信息,而且對其進行批量處理(例如配合 MapReduce 爲文檔創建倒排索引,計算網頁 PageRank 等)。和結構化存儲系統相比,雖然分佈式文件系統的可擴展性、吞吐率都很是好,可是幾乎沒法支持隨機訪問(Random Access)操做,一般只能進行文件進行追加(Append)操做。而這樣的限制使得非結構化存儲系統很難面對那些低延時,實時性較強的應用。
半結構化存儲 (Semi-structure Storage Systems)的提出即是爲了解決非結構化存儲系統隨機訪問性能差的問題。咱們一般會聽到一些流行的名詞,好比 NoSQL、Key-Value Store, 甚至包括對象存儲,例如 Protobuf、Thrift 等等。這些都屬於半結構化存儲研究的領域,其中以 NoSQL 近幾年的發展勢頭尤其強勁。NoSQL 系統既有分佈式文件系統所具備的可擴展性,又有結構化存儲系統的隨機訪問能力(例如隨機 Update、Read 操做),系統在設計時一般選擇簡單鍵值(K-V)進行存儲,拋棄了傳統 RDBMS 裏複雜 SQL 查詢以及 ACID 事務。這樣作能夠換取系統最大限度的可擴展性和靈活性。在 NoSQL 裏比較有名系統包括:Google 的 Bigtable、Amazon 的 Dynamo,以及開源界大名鼎鼎的 HBase、Cassandra 等。一般這些 NoSQL 系統底層都是基於比較成熟的存儲引擎,好比 Bigtable 就是基於 LevelDB(Jeff dean 寫的,很是好的 C++ 源碼教程),底層數據結構採用 LSM-Tree,除了 LSM-Tree 以外 B-Tree (B+Tree)也是很成熟的存儲引擎數據結構。
In-memory 存儲:隨着業務的併發愈來愈高,存儲系統對低延遲的要求也愈來愈高。 同時因爲摩爾定律以及內存的價格不斷降低,基於內存的存儲系統也開始普及。In-memory 存儲顧名思義就是將數據存儲在內存中, 從而得到讀寫的高性能。比較有名的系統包括 Memcahed ,以及 Redis。 這些基於 K-V 鍵值系統的主要目的是爲基於磁盤的存儲系統作 Cache。還有一些偏向於內存計算的系統,好比能夠追溯到普林斯頓 Kai Lee 教授早期的研究工做 Distributed Shared Memory ( DSM ),斯坦福的 RamCloud,以及最近比較火的基於 Lineage 技術的 Tachyon(Alluxio)項目(Spark 生態系統子項目)等等。
NewSQL:咱們在介紹結構化存儲時說到,單機 RDBMS 系統在可擴展性上面臨着巨大的挑戰,然而 NoSQL 不能很好地支持關係模型。那是否是有一種系統能兼備 RDBMS 的特性(例如:完整的 SQL 支持,ACID 事務支持),又能像 NoSQL 系統那樣具備強大的可擴展能力呢? 2012 年 Google 在 OSDI 上發表的 Spanner,以及 2013 年在 SIGMOD 發表的 F1,讓業界第一次看到了關係模型和 NoSQL 在超大規模數據中心上融合的可能性。不過因爲這些系統都太過於黑科技了,沒有大公司支持應該是作不出來的。好比 Spanner 裏用了原子鐘這樣的黑科技來解決時鐘同步問題,打破光速傳輸的限制。在這裏只能對 Google 表示膜拜。
咱們在以前提到,分佈式存儲系統有一系列的理論、算法、技術做爲支撐:例如 Paxos、CAP、Consistent Hash、Timing(時鐘)、2PC、3PC 等等。那麼如何掌握好這些技術呢?以我我的的經驗,掌握這些內容必定要理解其對應的上下文。什麼意思呢?就是必定要去思考爲何在當下環境須要某項技術,若是沒有這個技術用其它技術替代是否可行,而不是一味地陷入大量的細節之中。例如:如何掌握好 Paxos? Paxos 本質上來講是一個三階段提交,更 high level 講是一個分佈式鎖。理解 Paxos 必須一步一步從最簡單的場景出發,好比從最簡單的 Master-backup 出發,發現不行;衍生出多數派讀寫,發現仍是不行,再到 Paxos。以後再瞭解其變種,好比 Fast Paxos、Multi-Paxos。同理爲何須要 Consistent Hash,咱們能夠先思考若是用簡單 Range Partition 劃分數據有什麼問題。再好比學習 2PC、3PC 這樣的技術時,能夠想一想他們和 Paxos 有什麼關係,可否替代 Paxos。
以上是我關於分佈式存儲系統內容的一些總結,推薦一些相關的論文 ,有興趣的讀者能夠看看:
http://www.eecg.toronto.edu/~ashvin/courses/ece1746/2003/reading/ghemawat-sosp03.pdf
http://lintool.github.io/UMD-courses/bigdata-2015-Spring/content/ChangFay_etal_OSDI2006.pdf
https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf
http://lintool.github.io/UMD-courses/bigdata-2015-Spring/content/Khurana_etal_2012.pdf
http://lintool.github.io/UMD-courses/bigdata-2015-Spring/content/Abadi_2012.pdf
https://www.usenix.org/conference/osdi12/technical-sessions/presentation/corbett
https://www.cs.cornell.edu/projects/ladis2009/papers/lakshman-ladis2009.pdf
https://homes.cs.washington.edu/~billhowe/mapreduce_a_major_step_backwards.html
http://lintool.github.io/UMD-courses/bigdata-2015-Spring/content/Stonebraker_etal_CACM2010.pdf
http://www.cs.cmu.edu/~pavlo/courses/fall2013/static/slides/mapreduce.pdf
分佈式計算系統
聊完了分佈式存儲系統,讓咱們來聊聊分佈式計算系統 :) 首先解決一個不少初學分佈式計算的同窗的疑惑:分佈式計算和並行計算是一回事嗎?最初我也有這樣的疑惑,而如今個人理解是這樣的:
傳統的並行計算要的是:投入更多機器,數據大小不變,計算速度更快。
分佈式計算要求:投入更多的機器,能處理更大的數據。
換句話說兩者的出發點從一開始就不一樣,一個強調 High Performance, 一個強調 Scalability。舉例來講,MapReduce 給業界帶來的真正思考是什麼?實際上是給咱們普及了 Google 這樣級別的公司對真正意義上的「大數據」的理解。由於在 04 年論文出來以前,搞並行計算的人壓根連 「容錯」的概念都沒有。換句話說,分佈式計算最爲核心的部分就是「容錯」,沒有容錯,分佈式計算根本無從談起。MapReduce 統要作成這個樣子(Map + Reduce),其實就是爲了容錯。
然而不少初學分佈式計算的同窗對容錯的概念多多少少是有誤解的。包括我在初學 MapReduce 的時候也會思考:好好的計算怎麼就會出錯了呢?一方面,因爲硬件的老化,有可能會致使某臺存儲設備沒有啓動起來,某臺機器的網卡壞了,甚至於計算運行過程當中斷電了,這些都是有可能的。然而最頻繁發生的錯誤是計算進程被殺掉。由於 Google 的運行環境是共有集羣,任何一個權限更高的進程均可能 Kill 掉你的計算進程。設想在一個擁有幾千臺機器的集羣中運行,一個進程都不被 Kill 掉的機率幾乎爲零。具體的容錯機制咱們會在後面介紹具體的系統時提到。
另外一個有意思的話題是,隨着機器學習技術的興起,愈來愈多的分佈式計算系統是爲了機器學習這樣的應用設計的,這也是我比較關注的研究領域,也會在後面重點談到。
如同分佈式存儲系統同樣,我對分佈式計算系統也作了一個分類,以下:
1. 傳統基於 MSG 的系統
2. MapReduce-like 系統
3. 圖計算系統
4. 基於狀態(State)的系統
5. Streaming 系統
固然不一樣的人可能會有不一樣的分類方法,不過大同小異。咱們接下來聊聊這些系統都在幹些什麼。
傳統基於MSG的系統:這類系統裏比較有表明性的就是 MPI (Message Passing Interface)。目前比較流行的兩個 MPI 實現是 MPICH2 和 OpenMPI。MPI 這個框架很是靈活,對程序的結構幾乎沒有太多約束,以致於你們有時把 MPI 稱爲一組接口 API, 而不是系統框架。在這些 API 裏最經常使用的兩個就是 send 和 recv 接口(還有一系列非阻塞擴展接口,例如:Isend、Irecv 等)。MPI 除了提供消息傳遞接口以外,其框架還實現了資源管理和分配,以及調度的功能。除此以外,MPI 在高性能計算裏也被普遍使用,一般能夠和 Infiniband 這樣的高速網絡無縫結合。
除了 send 和 recv 接口以外,MPI 中另外一個接口也值得注意,那就是 AllReduce。這個接口在不少機器學習系統開發裏都很用。由於不少並行機器學習系統都是各個進程分別訓練模型,而後在合適的時候(例如一輪迭代結束)你們同步一下答案,達成共識,而後繼續迭代。這個 「達成共識」 的操做每每能夠很方便地經過 AllReduce 來完成。 AllReduce 接口具備兩個優勢:高效和使用簡單。 先說說爲何使用簡單:使用 AllReduce 一般只須要在單機核心源碼里加入 AllReduce 一行代碼,就能完成並行化的功能。說 AllReduce 高效的緣由是由於其底層消息傳遞使用了 Tree Aggregation,儘量地將計算分攤到每個節點。
但是,既然 AllReduce 這麼好,爲何在實際大規模計算中不多看到呢?緣由很簡單,就是由於 MPI 不支持容錯,因此很難擴展到大規模集羣之上。不過最近陳天奇寫了一個支持容錯的 AllReduce 接口,叫 Rabit,有興趣的同窗能夠關注一下。 大名鼎鼎的 XGBoost 底層的分佈式接口就是 Rabit。
MapReduce-like 系統:這一類系統又叫做 Dataflow 系統,其中以 MapReduce(Hadoop)和 Spark 爲表明。其實在學術界有不少相似的系統例如 Dryad、FlumeJava、Twister 等等。這一類系統的特色是將計算抽象成爲 High-Level Operator,例如像 Map、Reduce、Filter 這樣的函數式算子,而後將算子組合成 DAG ,而後由後端的調度引擎進行並行化調度。其中,MapReduce 系統屬於比較簡單的 DAG,只有 Map 和 Reduce 兩層節點。MapReduce 這樣的系統之因此能夠擴展到超大規模的集羣上運行,就是由於其完備的容錯機制。在 Hadoop 社區還有不少基於 MapReduce 框架的衍生產品,好比 Hive(並行數據庫 OLAP)、Pig(交互式數據操做)等等。
MapReduce-like 的編程風格和 MPI 截然相反。MapReduce對程序的結構有嚴格的約束——計算過程必須能在兩個函數中描述:Map 和 Reduce;輸入和輸出數據都必須是一個一個的 Records;任務之間不能通訊,整個計算過程當中惟一的通訊機會是 Map Phase 和 Reduce Phase 之間的 Shuffuling Phase,這是在框架控制下的,而不是應用代碼控制的。由於有了嚴格的控制,系統框架在任什麼時候候出錯均可以從上一個狀態恢復。Spark 的 RDD 則是利用 Lineage,可讓數據在內存中完成轉換。
因爲良好的擴展性,許多人都將機器學習算法的並行化任務放在了這些平臺之上。比較有名的庫包括 Mahout(基於 Hadoop),以及 MLI (基於 Spark) 。然而這些系統最大缺點有兩點:
1. 這些系統所能支持的機器學習模型一般都不是很大。致使這個問題的主要緣由是這系統在 push back 機器學習模型時都是粗粒度地把整個模型進行回傳,致使了網絡通訊的瓶頸。有些機器學習的模型能夠大到沒法想象,好比咱們用 Field-aware Factorization Machine (FFM)作 Criteo 的 CTR Prediction 時模型大小能夠達到 100 GB.
2. 嚴格的 BSP 同步計算使得集羣的效率變得很低。也就是說系統很容易受到 straggle 的影響。
圖計算系統:圖計算系統是分佈式計算裏另外一個分支,這些系統都是把計算過程抽象成圖,而後在不一樣節點分佈式執行,例如 PageRank 這樣的任務,很適合用圖計算系統來表示。最先成名的圖計算系統當屬 Google 的 Pregel,該系統採用 BSP 模型,計算以 Vectex 爲中心。隨後又有一系列圖計算框架推出,例如:GPS (對 Pregel 作了優化,除了 Vectex-centric Computation,還有 Global Computation,動態調整分區等等。)Giraph / Hama 都是基於 Hadoop 的 Apache 的開源 BSP 圖計算項目。
除了同步(BSP)圖計算系統以外,異步圖計算系統裏的佼佼者當屬 GraphLab,該系統提出了 GAS 的編程模型。目前這個項目已經更名爲 Dato,專門推廣基於圖的大規模機器學習系統。
基於狀態(State)的系統:這一類系統主要包括 2010 年 OSDI 上推出的 Piccolo,以及後來 2012 年 NIPS 上 Google 推出的 DistBelief,再到後來被機器系學習領域普遍應用的 Parameter Server 架構。這裏咱們重點介紹一下 Parameter Server 這個架構。
咱們以前說,MPI 因爲不支持容錯因此很難擴展至大規模集羣之中;MapReduce 系統沒法支持大模型機器學習應用,而且節點同步效率較低。用圖抽象來作機器學習任務,不少問題都不能很好地求解,好比深度學習中的多層結構。而 Parameter Server 這種 State-Centric 模型則把機器學習的模型存儲參數上升爲主要組件,而且採用異步機制提高處理能力。參數服務器的概念最先來自於 Alex Smola 於 2010 年提出的並行 LDA 架構。它經過採用分佈式的 Memcached 做爲存放參數的存儲,這樣就提供了有效的機制做用於不一樣Worker節點同步模型參數。Google 的 Jeff Dean 在 2012 年進一步提出了第一代 Google Brain 大規模神經網絡的解決方案 Distbelief。後來 CMU 的 Eric xing 以及百度少帥李沐都提出了更通用的 Parameter server 架構。
若是要深刻 Parameter Server 系統的設計,須要一些機器學習的背景,好比什麼是 SSP 協議, 在此咱們就不詳細討論了。
Streaming 系統:Streaming 系統聽名字就能看出來是爲流式數據提供服務的。其中比較有名的系統包括 Storm、Spark Streaming、Flink 等等。因爲本人對這個領域並非很熟,就不詳細介紹了。
以上是我對分佈式計算系統的一些介紹,其實每個方向深刻下去都是一個研究領域,在此推薦一些論文:
MapReduce: Simplified Data Processing on Large Clusters
Resilient Distributed Datasets
Scaling Distributed Machine Learning with the Parameter Server
Distributed GraphLab: A Framework for Machine Learning
Piccolo: Building Fast, Distributed Programs with Partitioned ..
Petuum: A New Platform for Distributed Machine Learning on Big Data
Spark Streaming
Dryad: Distributed Data-parallel Programs from Sequential Building ...
Large Scale Distributed Deep Networks - NIPS Proceedings
-End-