大規模數據處理的演化歷程

大數據如果從 Google 對外發布 MapReduce 論文算起,已經前後跨越十五年,我打算在本文和你蜻蜓點水般一起瀏覽下大數據的發展史,我們從最開始 MapReduce 計算模型開始,一路走馬觀花看看大數據這十五年關鍵發展變化,同時也順便會講解流式處理這個領域是如何發展到今天的這幅模樣。這其中我也會加入一些我對一些業界知名大數據處理系統 (可能裡面有些也不那麼出名) 的觀察和評論,同時考慮到我很有可能簡化、低估甚至於忽略了很多重要的大數據處理系統,我也會附帶一些參考材料幫助大家學習更多更詳細的知識。

另外,我們僅僅討論了大數據處理中偏 MapReduce/Hadoop 系統及其派系分支的大數據處理。我沒有討論任何 SQL 引擎 [1],我們同樣也沒有討論 HPC 或者超級計算機。儘管我這章的標題聽上去領域覆蓋非常廣泛,但實際上我僅僅會討論一個相對比較垂直的大數據領域。

本文裡面提到一些 Google 的技術的兩個原因:1)大數據對谷歌來說一直很重要,因此在那裡創造了許多有價值的東西值得詳細討論,2)我的經驗一直是 谷歌以外的人似乎更喜歡學習 Google 所做的事情,因為 Google 公司在這方面一直有點守口如瓶。

圖 10-1 本章討論各個大數據系統時間表

為了使我們這一次大數據旅行顯得更加具體有條理,我們設計了圖 10-1 的時間表,這張時間表概括地展示了不同系統的誕生日期。

在每一個系統介紹過程中,我會儘可能說明清楚該系統的簡要歷史,並且我會嘗試從流式處理系統的演化角度來闡釋該系統對演化過程的貢獻。最後,我們將回顧以上系統所有的貢獻,從而全面了解上述系統如何演化並構建出現代流式處理系統的。

MapReduce

我們從 MapReduce 開始我們的旅程。

圖 10-2 MapReduce 的時間表

我認為我們可以很確定地說,今天我們討論的大規模數據處理系統都源自於 2003 年 MapReduce。當時,谷歌的工程師正在構建各種定製化系統,以解決互聯網時代下大數據處理難題。當他們這樣嘗試去解決這些問題時候,發現有三個難以逾越的坎兒:

  • 數據處理很難 只要是數據科學家或者工程師都很清楚。如果你能夠精通於從原始數據挖掘出對企業有價值的信息,那這個技能能夠保你這輩子吃喝不愁。
  • 可伸縮性很難 本來數據處理已經夠難了,要從大規模數據集中挖掘出有價值的數據更加困難。
  • 容錯很難 要從大規模數據集挖掘數據已經很難了,如果還要想辦法在一批廉價機器構建的分散式集群上可容錯地、準確地方式挖掘數據價值,那真是難於上青天了。

在多種應用場景中都嘗試解決了上述三個問題之後,Google 的工程師們開始注意到各自構建的定製化系統之間頗有相似之處。最終,Google 工程師悟出來一個道理: 如果他們能夠構建一個可以解決上述問題二和問題三的框架,那麼工程師就將可以完全放下問題二和三,從而集中精力解決每個業務都需要解決的問題一。於是,MapReduce 框架誕生了。

MapReduce 的基本思想是提供一套非常簡潔的數據處理 API,這套 API 來自於函數式編程領域的兩個非常易於理解的操作:map 和 reduce(圖 10-3)。使用該 API 構建的底層數據流將在這套分散式系統框架上執行,框架負責處理所有繁瑣的可擴展性和容錯性問題。可擴展性和容錯性問題對於分散式底層工程師來說無疑是非常有挑戰的課題,但對於我們普通工程師而言,無益於是災難。

圖 10-3 MapReduce 作業原理圖

我們已經在第 6 章詳細討論了 MapReduce 的語義,所以我們在此不再贅述。僅僅簡單地回想一下,我們將處理過程分解為六個離散階段(MapRead,Map,MapWrite,ReduceRead,Reduce,ReduceWrite)作為對於流或者表進行分析的幾個步驟。我們可以看到,整體上 Map 和 Reduce 階段之間差異其實也不大 ; 更高層次來看,他們都做了以下事情:

  • 從表中讀取數據,並轉換為數據流 (譯者注: 即 MapRead、ReduceRead)
  • 針對上述數據流,將用戶編寫業務處理代碼應用於上述數據流,轉換並形成新的一個數據流。 (譯者注: 即 Map、Reduce)
  • 將上述轉換後的流根據某些規則分組,並寫出到表中。 (譯者注: 即 MapWrite、ReduceWrite)

隨後,Google 內部將 MapReduce 投入生產使用並得到了非常廣泛的業務應用,Google 認為應該和公司外的同行分享我們的研究成果,最終我們將 MapReduce 論文發表於 OSDI 2004(見圖 10-4)。

圖 10-4 MapReduce 論文發表在 OSDI 2004 上

論文中,Google 詳細描述了 MapReduce 項目的歷史,API 的設計和實現,以及有關使用了 MapReduce 框架的許多不同生產案例的詳細信息。當然,Google 沒有提供任何實際的源代碼,以至於最終 Google 以外的人都認為:「是的,這套系統確實牛啊!」,然後立馬回頭去模仿 MapReduce 去構建他們的定製化系統。

在隨後這十年的過程中,MapReduce 繼續在谷歌內部進行大量開發,投入大量時間將這套系統規模推進到前所未有的水平。如果讀者朋友希望了解一些更加深入更加詳細的 MapReduce 說明,我推薦由我們的 MapReduce 團隊中負責擴展性、性能優化的大牛 Maria?n Dvorsky?撰寫的文章《History of massive-scale sorting experiments at Google》(圖 10-5)

圖 10-5 MariánDvorsky的《History of massive-scale sorting experiments》博客文章

我這裡希望強調的是,這麼多年來看,其他任何的分散式架構最終都沒有達到 MapReduce 的集群規模,甚至在 Google 內部也沒有。從 MapReduce 誕生起到現在已經跨越十載之久,都未能看到真正能夠超越 MapReduce 系統規模的另外一套系統,足見 MapReduce 系統之成功。14 年的光陰看似不長,對於互聯網行業已然永久。

從流式處理系統來看,我想為讀者朋友強調的是 MapReduce 的簡單性和可擴展性。 MapReduce 給我們的啟發是:MapReduce 系統的設計非常勇於創新,它提供一套簡便且直接的 API,用於構建業務複雜但可靠健壯的底層分散式數據 Pipeline,並足夠將這套分散式數據 Pipeline 運行在廉價普通的商用伺服器集群之上。

Hadoop

我們大數據旅程的下一站是 Hadoop(圖 10-6)。需要著重說明的是:我為了保證我們討論的重心不至於偏離太多,而壓縮簡化討論 Hadoop 的內容。但必須承認的是,Hadoop 對我們的行業甚至整個世界的影響不容小覷,它帶來的影響遠遠超出了我在此書討論的範圍。

圖 10-6 Hadoop 的時間表

Hadoop 於 2005 年問世,當時 Doug Cutting 和 Mike Cafarella 認為 MapReduce 論文中的想法太棒了,他們在構建 Nutch webcrawler 的分散式版本正好需要這套分散式理論基礎。在這之前,他們已經實現了自己版本的 Google 分散式文件系統(最初稱為 Nutch 分散式文件系統的 NDFS,後來改名為 HDFS 或 Hadoop 分散式文件系統)。因此下一步,自然而然的,基於 HDFS 之上添加 MapReduce 計算層。他們稱 MapReduce 這一層為 Hadoop。

Hadoop 和 MapReduce 之間的主要區別在於 Cutting 和 Cafarella 通過開源(以及 HDFS 的源代碼)確保 Hadoop 的源代碼與世界各地可以共享,最終成為 Apache Hadoop 項目的一部分。雅虎聘請 Cutting 來幫助將雅虎網路爬蟲項目升級為全部基於 Hadoop 架構,這個項目使得 Hadoop 有效提升了生產可用性以及工程效率。自那以後,整個開源生態的大數據處理工具生態系統得到了蓬勃發展。與 MapReduce 一樣,相信其他人已經能夠比我更好地講述了 Hadoop 的歷史。我推薦一個特別好的講解是 Marko Bonaci 的《The history of Hadoop》,它本身也是一本已經出版的紙質書籍(圖 10-7)。

圖 10-7 Marko Bonaci 的《The history of Hadoop》

在 Hadoop 這部分,我期望讀者朋友能夠了解到圍繞 Hadoop 的開源生態系統對整個行業產生的巨大影響。通過創建一個開放的社區,工程師可以從早期的 GFS 和 MapReduce 論文中改進和擴展這些想法,這直接促進生態系統的蓬勃發展,並基於此之上產生了許多有用的工具,如 Pig,Hive,HBase,Crunch 等等。這種開放性是導致我們整個行業現有思想多樣性的關鍵,同時 Hadoop 開放性生態亦是直接促進流計算系統發展。

Flume

我們現在再回到 Google,討論 Google 公司中 MapReduce 的官方繼承者:Flume([圖 10-8],有時也稱為 FlumeJava,這個名字起源於最初 Flume 的 Java 版本。需要注意的是,這裡的 Flume 不要與 Apache Flume 混淆,這部分是面向不同領域的東西,只是恰好有同樣的名字)。

圖 10-8 Flume 的時間表

Flume 項目由 Craig Chambers 在 2007 年穀歌西雅圖辦事處成立時發起。Flume 最初打算是希望解決 MapReduce 的一些固有缺點,這些缺點即使在 MapReduce 最初大紅大紫的階段已經非常明顯。其中許多缺點都與 MapReduce 完全限定的 Map→Shuffle→Reduce 編程模型相關 ; 這個編程模型雖然簡單,但它帶來了一些缺點:

  • 由於單個 MapReduce 作業並不能完成大量實際上的業務案例,因此許多定製的編排系統開始在 Google 公司內部出現,這些編排系統主要用於協調 MapReduce 作業的順序。這些系統基本上都在解決同一類問題,即將多個 MapReduce 作業粘合在一起,創建一個解決複雜問題的數據管道。然而,這些編排系統都是 Google 各自團隊獨立開發的,相互之間也完全不兼容,是一類典型的重複造輪子案例。
  • 更糟糕的是,由於 MapReduce 設計的 API 遵循嚴格結構,在很多情況下嚴格遵循 MapReduce 編程模型會導致作業運行效率低下。例如,一個團隊可能會編寫一個簡單地過濾掉一些元素的 MapReduce,即,僅有 Map 階段沒有 Reduce 階段的作業。這個作業下游緊接著另一個團隊同樣僅有 Map 階段的作業,進行一些欄位擴展和豐富 (仍然帶一個空的 Reduce 階段作業)。第二個作業的輸出最終可能會被第三個團隊的 MapReduce 作業作為輸入,第三個作業將對數據執行某些分組聚合。這個 Pipeline,實際上由一個合併 Map 階段 (譯者注: 前面兩個 Map 合併為一個 Map),外加一個 Reduce 階段即可完成業務邏輯,但實際上卻需要編排三個完全獨立的作業,每個作業通過 Shuffle 和 Output 兩個步驟鏈接在一起。假設你希望保持代碼的邏輯性和清潔性,於是你考慮將部分代碼進行合併,但這個最終導致第三個問題。
  • 為了優化 MapReduce 作業中的這些低效代碼,工程師們開始引入手動優化,但不幸的是,這些優化會混淆 Pipeline 的簡單邏輯,進而增加維護和調試成本。

Flume 通過提供可組合的高級 API 來描述數據處理流水線,從而解決了這些問題。這套設計理念同樣也是 Beam 主要的抽象模型,即 PCollection 和 PTransform 概念,如圖 10-9 所示。

圖 10-9 Flume 的高層抽象模型(圖片來源:Frances Perry)

這些數據處理 Pipeline 在作業啟動時將通過優化器生成,優化器將以最佳效率生成 MapReduce 作業,然後交由框架編排執行。整個編譯執行原理圖可以在圖 10-10 中看到。

圖 10-10 從邏輯管道到物理執行計劃的優化

也許 Flume 在自動優化方面最重要的案例就是是合併(Reuven 在第 5 章中討論了這個主題),其中兩個邏輯上獨立的階段可以在同一個作業中順序地(消費者 - 生產者融合)執行或者並行執行(兄弟融合),如圖 10-11 所示。

圖 10-11 合併優化將順序或並行操作 (運算元) 組合在一起,到同一個操作 (運算元)。

將兩個階段融合在一起消除了序列化 / 反序列化和網路開銷,這在處理大量數據的底層 Pipeline 中非常重要。

另一種類型的自動優化是 combiner lifting(見圖 10-12),當我們討論增量合併時,我們已經在第 7 章中討論了這些機制。combiner lifting 只是我們在該章討論的多級組合邏輯的編譯器自動優化:以求和操作為例,求和的合併邏輯本來應該運算在分組 (譯者注: 即 Group-By) 操作後,由於優化的原因,被提前到在 group-by-key 之前做局部求和(根據 group-by-key 的語義,經過 group-by-key 操作需要跨網路進行大量數據 Shuffle)。在出現數據熱點情況下,將這個操作提前可以大大減少通過網路 Shuffle 的數據量,並且還可以在多台機器上分散掉最終聚合的機器負載。

圖 10-12: combiner lifting 在數據上游直接進行局部聚合後再發送給下游端進行二次聚合。

由於其更清晰的 API 定義和自動優化機制,在 2009 年初 Google 內部推出後 FlumeJava 立即受到巨大歡迎。之後,該團隊發表了題為《Flume Java: Easy, Efficient Data-Parallel Pipelines》(storage.googleapis.com/) 的論文(參見圖 10-13),這篇論文本身就是一個很好的學習 FlumeJava 的資料。

圖 10-13 FlumeJava 的論文

Flume C++ 版本很快於 2011 年發布。之後 2012 年初,Flume 被引入為 Google 的所有新工程師提供的 Noogler6 培訓內容。MapReduce 框架於是最終被走向被替換的命運。

從那時起,Flume 已經遷移到不再使用 MapReduce 作為執行引擎 ; 相反,Flume 底層基於一個名為 Dax 的內置自定義執行引擎。 工作本身。不僅讓 Flume 更加靈活選擇執行計劃而不必拘泥於 Map→Shuffle→Reduce MapReduce 的模型,Dax 還啟用了新的優化,例如 Eugene Kirpi-chov 和 Malo Denielou 的《No shard left behind》博客文章(cloud.google.com/blog/p) 中描述的動態負載均衡(圖 10-14)。

圖 10-14 帖子 《No shard left behind》

儘管那篇博客主要是基於 Google DataFlow 框架下討論問題,但動態負載均衡(或液態分片,Google 內部更習慣這樣叫)可以讓部分已經完成工作的 Worker 能夠從另外一些繁忙的 Worker 手中分配一些額外的工作。在 Job 運行過程中,通過不斷的動態調整負載分配可以將系統運行效率趨近最優,這種演算法將比傳統方法下有經驗工程師手工設置的初始參數性能更好。Flume 甚至為 Worker 池變化進行了適配,一個拖慢整個作業進度的 Worker 會將其任務轉移到其他更加高效的 Worker 上面進行執行。Flume 的這些優化手段,在 Google 內部為公司節省了大量資源。

最後一點,Flume 後來也被擴展為支持流語義。除 Dax 作為一個批處理系統引擎外,Flume 還擴展為能夠在 MillWheel 流處理系統上執行作業(稍後討論)。在 Google 內部,之前本書中討論過的大多數高級流處理語義概念首先被整合到 Flume 中,然後才進入 Cloud Dataflow 並最終進入 Apache Beam。

總而言之,本節我們主要強調的是 Flume 產品給人引入高級管道概念,這使得能夠讓用戶編寫清晰易懂且自動優化的分散式大數據處理邏輯,從而讓創建更大型更複雜的分散式大數據任務成為了可能,Flume 讓我們業務代碼在保持代碼清晰邏輯乾淨的同時,自動具備編譯器優化能力。

Storm

接下來是 Apache Storm(圖 10-15),這是我們研究的第一個真正的流式系統。 Storm 肯定不是業界使用最早的流式處理系統,但我認為這是整個行業真正廣泛採用的第一個流式處理系統,因此我們在這裡需要仔細研究一下。

圖 10-15 Storm 的時間軸

Storm 是 Nathan Marz 的心血結晶,Nathan Marz 後來在一篇題為《History of Apache Storm and lessons learned》的博客文章(nathanmarz.com/blog/his) 中記錄了其創作歷史(圖 10-16)。 這篇冗長的博客講述了 BackType 這家創業公司一直在自己通過消息隊列和自定義代碼去處理 Twitter 信息流。Nathan 和十幾年前 Google 裡面設計 MapReduce 相關工程師有相同的認識:實際的業務處理的代碼僅僅是系統代碼很小一部分,如果有個統一的流式實時處理框架負責處理各類分散式系統底層問題,那麼基於之上構建我們的實時大數據處理將會輕鬆得多。基於此,Nathan 團隊完成了 Storm 的設計和開發。

值得一提的是,Storm 的設計原則和其他系統大相徑庭,Storm 更多考慮到實時流計算的處理時延而非數據的一致性保證。後者是其他大數據系統必備基礎產品特徵之一。Storm 針對每條流式數據進行計算處理,並提供至多一次或者至少一次的語義保證;同時不提供任何狀態存儲能力。相比於 Batch 批處理系統能夠提供一致性語義保證,Storm 系統能夠提供更低的數據處理延遲。對於某些數據處理業務場景來說,這確實也是一個非常合理的取捨。

圖 10-16 《History of Apache Storm and lessons learned》

不幸的是,人們很快就清楚地知道他們想要什麼樣的流式處理系統。他們不僅希望快速得到業務結果,同時希望系統具有低延遲和準確性,但僅憑 Storm 架構實際上不可能做到這一點。針對這個情況,Nathan 後面又提出了 Lambda 架構。

鑒於 Storm 的局限性,聰明的工程師結合弱一致語義的 Storm 流處理以及強一致語義的 Hadoop 批處理。前者產生了低延遲,但不精確的結果,而後者產生了高延遲,但精確的結果,雙劍合璧,整合兩套系統整體提供的低延遲但最終一致的輸出結果。我們在第 1 章中了解到,Lambda 架構是 Marz 的另一個創意,詳見他的文章《「如何擊敗 CAP 定理」》(nathanmarz.com/blog/how) (圖 10-17)。

圖 10-17 《How to beat the CAP theorem》

我已經花了相當多的時間來分析 Lambda 架構的缺點,以至於我不會在這裡啰嗦這些問題。但我要重申一下:儘管它帶來了大量成本問題,Lambda 架構當前還是非常受歡迎,僅僅是因為它滿足了許多企業一個關鍵需求:系統提供低延遲但不準確的數據,後續通過批處理系統糾正之前數據,最終給出一致性的結果。從流處理系統演變的角度來看,Storm 確實為普羅大眾帶來低延遲的流式實時數據處理能力。然而,它是以犧牲數據強一致性為代價的,這反過來又帶來了 Lambda 架構的興起,導致接下來多年基於兩套系統架構之上的數據處理帶來無盡的麻煩和成本。

撇開其他問題先不說,Storm 是行業首次大規模嘗試低延遲數據處理的系統,其影響反映在當前線上大量部署和應用各類流式處理系統。在我們要放下 Storm 開始聊其他系統之前,我覺得還是很有必要去說說 Heron 這個系統。在 2015 年,Twitter 作為 Storm 項目孵化公司以及世界上已知最大的 Storm 用戶,突然宣布放棄 Storm 引擎,宣稱正在研發另外一套稱之為 Heron 的流式處理框架。Heron 旨在解決困擾 Storm 的一系列性能和維護問題,同時向 Storm 保持 API 兼容,詳見題為《Twitter Heron:Stream Processing at scale》的論文(semanticscholar.org/pap) (圖 10-18)。

圖 10-18 Heron 的論文

Heron 本身也是開源產品(但開源不在 Apache 項目中)。鑒於 Storm 仍然在社區中持續發展,現在又冒出一套和 Storm 競爭的軟體,最終兩邊系統鹿死誰手,我們只能拭目以待了。


Spark

繼續走起,我們現在來到 Apache Spark(圖 10-19)。再次,我又將大量簡化 Spark 系統對行業的總體影響探討,僅僅關注我們的流處理領域部分。

圖 10-19 Spark 的時間軸

Spark 在 2009 年左右誕生於加州大學伯克利分校的著名 AMPLab。最初推動 Spark 成名的原因是它能夠經常在內存執行大量的計算工作,直到作業的最後一步才寫入磁碟。工程師通過彈性分散式數據集(RDD)理念實現了這一目標,在底層 Pipeline 中能夠獲取每個階段數據結果的所有派生關係,並且允許在機器故障時根據需要重新計算中間結果,當然,這些都基於一些假設 a)輸入是總是可重放的,b)計算是確定性的。對於許多案例來說,這些先決條件是真實的,或者看上去足夠真實,至少用戶確實在 Spark 享受到了巨大的性能提升。從那時起,Spark 逐漸建立起其作為 Hadoop 事實上的繼任產品定位。

在 Spark 創建幾年後,當時 AMPLab 的研究生 Tathagata Das 開始意識到:嘿,我們有這個快速的批處理引擎,如果我們將多個批次的任務串接起來,用它能否來處理流數據?於是乎,Spark Streaming 誕生了。

關於 Spark Streaming 的真正精彩之處在於:強大的批處理引擎解決了太多底層麻煩的問題,如果基於此構建流式處理引擎則整個流處理系統將簡單很多,於是世界又多一個流處理引擎,而且是可以獨自提供一致性語義保障的流式處理系統。換句話說,給定正確的用例,你可以不用 Lambda 架構系統直接使用 Spark Streaming 即可滿足數據一致性需求。為 Spark Streaming 手工點贊!

這裡的一個主要問題是「正確的用例」部分。早期版本的 Spark Streaming(1.x 版本)的一大缺點是它僅支持特定的流處理語義:即,處理時間窗口。因此,任何需要使用事件時間,需要處理延遲數據等等案例都無法讓用戶使用 Spark 開箱即用解決業務。這意味著 Spark Streaming 最適合於有序數據或事件時間無關的計算。而且,正如我在本書中重申的那樣,在處理當今常見的大規模、以用戶為中心的數據集時,這些先決條件看上去並不是那麼常見。

圍繞 Spark Streaming 的另一個有趣的爭議是「microbatch 和 true streaming」爭論。由於 Spark Streaming 建立在批處理引擎的重複運行的基礎之上,因此批評者聲稱 Spark Streaming 不是真正的流式引擎,因為整個系統的處理基於全局的數據切分規則。這個或多或少是實情。儘管流處理引擎幾乎總是為了吞吐量而使用某種批處理或者類似的加大吞吐的系統策略,但它們可以靈活地在更精細的級別上進行處理,一直可以細化到某個 key。但基於微批處理模型的系統在基於全局切分方式處理數據包,這意味著同時具備低延遲和高吞吐是不可能的。確實我們看到許多基準測試表明這說法或多或少有點正確。當然,作業能夠做到幾分鐘或幾秒鐘的延遲已經相當不錯了,實際上生產中很少有用例需要嚴格數據正確性和低延遲保證。所以從某種意義上說,Spark 瞄準最初目標客戶群體打法是非常到位的,因為大多數業務場景均屬於這一類。但這並未阻止其競爭對手將此作為該平台的巨大劣勢。就個人而言,在大多數情況下,我認為這只是一個很小問題。

撇開缺點不說,Spark Streaming 是流處理的分水嶺:第一個廣泛使用的大規模流處理引擎,它也可以提供批處理系統的正確性保證。 當然,正如前面提到的,流式系統只是 Spark 整體成功故事的一小部分,Spark 在迭代處理和機器學習領域做出了重要貢獻,其原生 SQL 集成以及上述快如閃電般的內存計算,都是非常值得大書特書的產品特性。

如果您想了解有關原始 Spark 1.x 架構細節的更多信息,我強烈推薦 Matei Zaharia 關於該主題的論文《 「An Architecture for Fast and General Data Processing on Large Clusters》(圖 10-20)。 這是 113 頁的 Spark 核心講解論文,非常值得一讀。

圖 10-20 Spark 的學位論文

時至今日,Spark 的 2.x 版本極大地擴展了 Spark Streaming 的語義功能,其中已經包含了本書中描述流式處理模型的許多部分,同時試圖簡化一些更複雜的設計。 Spark 甚至推出了一種全新的、真正面向流式處理的架構,用以規避掉微批架構的種種問題。但是曾經,當 Spark 第一次出現時,它帶來的重要貢獻是它是第一個公開可用的流處理引擎,具有數據處理的強一致性語義,儘管這個特性只能用在有序數據或使用處理時間計算的場景。

MillWheel

接下來我們討論 MillWheel,這是我在 2008 年加入 Google 後的花 20%時間兼職參與的項目,後來在 2010 年全職加入該團隊(圖 10-21)。

圖 10-21 MillWheel 時間表

MillWheel 是 Google 最早的通用流處理架構,該項目由 Paul Nordstrom 在 Google 西雅圖辦事處開業時發起。 MillWheel 在 Google 內的成功與長期以來一直致力於為無序數據提供低延遲,強一致的處理能力不無關係。在本書的講解中,我們已經多次分別討論了促使 MillWheel 成為一款成功產品的方方面面。

  • 第五章,Reuven 詳細討論過數據精準一次的語義保證。精準一次的語義保證對於正確性至關重要。
  • 第七章,我們研究了狀態持久化,這為在不那麼靠譜的普通硬體上執行的長時間數據處理業務並且需要保證正確性奠定了基礎。
  • 第三章,Slava 討論了 Watermark。Watermark 為處理無序數據提供了基礎。
  • 第七章,我們研究了持久性計時器,它們提供了 Watermark 與業務邏輯之間的某些關聯特性。

有點令人驚訝的是,MillWheel 項目最開始並未關注數據正確性。保羅最初的想法更接近於 Storm 的設計理論:具有弱一致性的低延遲數據處理。這是最初的 MillWheel 客戶,一個關於基於用戶搜索數據構建會話和另一個對搜索查詢執行異常檢測(來自 MillWheel 論文的 Zeitgeist 示例),這兩家客戶迫使項目走向了正確的方向。兩者都非常需要強一致的數據結果:會話用於推斷用戶行為,異常檢測用於推斷搜索查詢的趨勢 ; 如果他們提供的數據不靠譜,兩者效果都會顯著下降。最終,幸運的是,MillWheel 的設計被客戶需求導向追求數據強一致性的結果。

支持亂序數據處理,這是現代流式處理系統的另一個核心功能。這個核心功能通常也被認為是被 MillWheel 引入到流式處理領域,和數據準確性一樣,這個功能也是被客戶需求推動最終加入到我們系統。 Zeitgeist 項目的大數據處理過程,通常被我們拿來用作一個真正的流式處理案例來討論。Zeitgeist 項目希望檢測識別搜索查詢流量中的異常,並且需要捕獲異常流量。對於這個大數據項目數據消費者來說,流計算將所有計算結果產出並讓用戶輪詢所有 key 用來識別異常顯然不太現實,數據用戶要求系統直接計算某個 key 出現異常的數據結果,而不需要上層再來輪詢。對於異常峰值(即查詢流量的增加),這還相對來說比較簡單好解決:當給定查詢的計數超過查詢的預期值時,系統發出異常信號。但是對於異常下降(即查詢流量減少),問題有點棘手。僅僅看到給定搜索詞的查詢數量減少是不夠的,因為在任何時間段內,計算結果總是從零開始。在這些情況下你必須確保你的數據輸入真的能夠代表當前這段時間真實業務流量,然後才將計算結果和預設模型進行比較。

真正的流式處理

「真正的流式處理用例」需要一些額外解釋。流式系統的一個新的演化趨勢是,捨棄掉部分產品需求以簡化編程模型,從而使整個系統簡單易用。例如,在撰寫本文時,Spark Structured Streaming 和 Apache Kafka Streams 都將系統提供的功能限制在第 8 章中稱為「物化視圖語義」範圍內,本質上對最終一致性的輸出表不停做數據更新。當您想要將上述輸出表作為結果查詢使用時,物化視圖語義非常匹配你的需求:任何時候我們只需查找該表中的值並且 (譯者注: 儘管結果數據一直在不停被更新和改變) 以當前查詢時間請求到查詢結果就是最新的結果。但在一些需要真正流式處理的場景,例如異常檢測,上述物化視圖並不能夠很好地解決這類問題。

接下來我們會討論到,異常檢測的某些需求使其不適合純物化視圖語義(即,依次針對單條記錄處理),特別當需要完整的數據集才能夠識別業務異常,而這些異常恰好是由於數據的缺失或者不完整導致的。另外,不停輪詢結果表以查看是否有異常其實並不是一個擴展性很好的辦法。真正的流式用戶場景是推動 watermark 等功能的原始需求來源。(Watermark 所代表的時間有先有後,我們需要最低的 Watermark 追蹤數據的完整性,而最高的 Watermark 在數據時間發生傾斜時候非常容易導致丟數據的情況發生,類似 Spark Structured Streaming 的用法)。省略類似 Watermark 等功能的系統看上去簡單不少,但換來代價是功能受限。在很多情況下,這些功能實際上有非常重要的業務價值。但如果這樣的系統聲稱這些簡化的功能會帶來系統更多的普適性,不要聽他們忽悠。試問一句,功能需求大量被砍掉,如何保證系統的普適性呢?

Zeitgeist 項目首先嘗試通過在計算邏輯之前插入處理時間的延遲數值來解決數據延遲問題。當數據按順序到達時,這個思路處理邏輯正常。但業務人員隨後發現數據有時可能會延遲很大,從而導致數據無序進入流式處理系統。一旦出現這個情況,系統僅僅採用處理時間的延遲是不夠的,因為底層數據處理會因為數據亂序原因被錯誤判斷為異常。最終,我們需要一種等待數據到齊的機制。

之後 Watermark 被設計出來用以解決數據亂序的問題。正如 Slava 在第 3 章中所描述的那樣,基本思想是跟蹤系統輸入數據的當前進度,對於每個給定的數據源,構建一個數據輸入進度用來表徵輸入數據的完整性。對於一些簡單的數據源,例如一個帶分區的 Kafka Topic,每個 Topic 下屬的分區被寫入的是業務時間持續遞增的數據(例如通過 Web 前端實時記錄的日誌事件),這種情況下我們可以計算產生一個非常完美的 Watermark。但對於一些非常複雜的數據輸入,例如動態的輸入日誌集,一個啟發式演算法可能是我們能夠設計出來最能解決業務問題的 Watermark 生成演算法了。但無論哪種方式,Watermark 都是解決輸入事件完整性最佳方式。之前我們嘗試使用處理時間來解決事件輸入完整性,有點驢頭不及馬嘴的感覺。

得益於客戶的需求推動,MillWheel 最終成為能夠支持無序數據的強大流處理引擎。因此,題為《MillWheel: Fault-Tolerant Stream Processing at Internet Scale》(圖 10-22)的論文花費大部分時間來討論在這樣的系統中提供正確性的各種問題,一致性保證、Watermark。如果您對這個主題感興趣,那值得花時間去讀讀這篇論文。

圖 10-22 MillWheel 論文

MillWheel 論文發表後不久,MillWheel 就成為 Flume 底層提供支撐的流式處理引擎,我們稱之為 Streaming Flume。今天在谷歌內部,MillWheel 被下一代理論更為領先的系統所替換: Windmill(這套系統同時也為 DataFlow 提供了執行引擎),這是一套基於 MillWheel 之上,博採眾家之長的大數據處理系統,包括提供更好的調度和分發策略、更清晰的框架和業務代碼解耦。

MillWheel 給我們帶來最大的價值是之前列出的四個概念(數據精確一次性處理,持久化的狀態存儲,Watermark,持久定時器)為流式計算提供了工業級生產保障:即使在不可靠的商用硬體上,也可以對無序數據進行穩定的、低延遲的處理。

Kafka

我們開始討論 Kafka(圖 10-23)。 Kafka 在本章討論的系統中是獨一無二的,因為它不是數據計算框架,而是數據傳輸和存儲的工具。但是,毫無疑問,Kafka 在我們正在討論的所有系統中扮演了推動流處理的最有影響力的角色之一。

圖 10-23 Kafka 的時間軸

如果你不熟悉它,我們可以簡單描述為: Kafka 本質上是一個持久的流式數據傳輸和存儲工具,底層系統實現為一組帶有分區結構的日誌型存儲。它最初是由 Neha Narkhede 和 Jay Kreps 等業界大牛在 LinkedIn 公司內部開發的,其卓越的特性有:

  • 提供一個乾淨的持久性模型,讓大家在流式處理領域裡面可以享受到批處理的產品特性,例如持久化、可重放。
  • 在生產者和消費者之間提供彈性隔離。
  • 我們在第 6 章中討論過的流和表之間的關係,揭示了思考數據處理的基本方式,同時還提供了和資料庫打通的思路和概念。
  • 來自於上述所有方面的影響,不僅讓 Kafka 成為整個行業中大多數流處理系統的基礎,而且還促進了流處理資料庫和微服務運動。

在這些特性中,有兩個對我來說最為突出。第一個是流數據的持久化和可重放性的應用。在 Kafka 之前,大多數流處理系統使用某種臨時、短暫的消息系統,如 Rabbit MQ 甚至是普通的 TCP 套接字來發送數據。數據處理的一致性往往通過生產者數據冗餘備份來實現(即,如果下游數據消費者出現故障,則上游生產者將數據進行重新發送),但是上游數據的備份通常也是臨時保存一下。大多數系統設計完全忽略在開發和測試中需要重新拉取數據重新計算的需求。但 Kafka 的出現改變了這一切。從資料庫持久日誌概念得到啟發並將其應用於流處理領域,Kafka 讓我們享受到了如同 Batch 數據源一樣的安全性和可靠性。憑藉持久化和可重放的特點,流計算在健壯性和可靠性上面又邁出關鍵的一步,為後續替代批處理系統打下基礎。

作為一個流式系統開發人員,Kafka 的持久化和可重放功能對業界產生一個更有意思的變化就是: 當今大量流處理引擎依賴源頭數據可重放來提供端到端精確一次的計算保障。可重放的特點是 Apex,Flink,Kafka Streams,Spark 和 Storm 的端到端精確一次保證的基礎。當以精確一次模式執行時,每個系統都假設 / 要求輸入數據源能夠重放之前的部分數據 (從最近 Checkpoint 到故障發生時的數據)。當流式處理系統與不具備重放能力的輸入源一起使用時(哪怕是源頭數據能夠保證可靠的一致性數據投遞,但不能提供重放功能),這種情況下無法保證端到端的完全一次語義。這種對可重放(以及持久化等其他特點)的廣泛依賴是 Kafka 在整個行業中產生巨大影響的間接證明。

Kafka 系統中第二個值得注意的重點是流和表理論的普及。我們花了整個第 6 章以及第 8 章、第 9 章來討論流和表,可以說流和表構成了數據處理的基礎,無論是 MapReduce 及其演化系統,SQL 資料庫系統,還是其他分支的數據處理系統。並不是所有的數據處理方法都直接基於流或者表來進行抽象,但從概念或者理論上說,表和流的理論就是這些系統的運作方式。作為這些系統的用戶和開發人員,理解我們所有系統構建的核心基礎概念意義重大。我們都非常感謝 Kafka 社區的開發者,他們幫助我們更廣泛更加深入地了解到批流理論。

如果您想了解更多關於 Kafka 及其理論核心,JackKreps 的《I?Logs》(OReilly; 圖 10-24)是一個很好的學習資料。另外,正如第 6 章中引用的那樣,Kreps 和 Martin Kleppmann 有兩篇文章(圖 10-25),我強烈建議您閱讀一下關於流和表相關理論。

圖 10-24 《I ? Logs》

Kafka 為流處理領域做出了巨大貢獻,可以說比其他任何單一系統都要多。特別是,對輸入和輸出流的持久性和可重放的設計,幫助將流計算從近似工具的小眾領域發展到在大數據領域婦孺皆知的程度起了很大作用。此外,Kafka 社區推廣的流和表理論對於數據處理引發了我們深入思考。

圖10-25 Martin 的帖子 (左邊) 以及 Jay 的帖子 (右邊)

DataFlow

Cloud Dataflow(圖 10-26)是 Google 完全託管的、基於雲架構的數據處理服務。 Dataflow 於 2015 年 8 月推向全球。DataFlow 將 MapReduce,Flume 和 MillWheel 的十多年經驗融入其中,並將其打包成 Serverless 的雲體驗。

圖 10-26 Google DataFlow 的時間軸

雖然 Google 的 Dataflow 的 Serverless 特點可能是從系統角度來看最具技術挑戰性以及有別於其他雲廠商產品的重要因素,但我想在此討論主要是其批流統一的編程模型。編程模型包括我們在本書的大部分內容中所討論的轉換,窗口,水印,觸發器和聚合計算。當然,所有這些討論都包含了思考問題的 what、where、when、how。

DataFlow 模型首先誕生於 Flume,因為我們希望將 MillWheel 中強大的無序數據計算能力整合到 Flume 提供的更高級別的編程模型中。這個方式可以讓 Google 員工在內部使用 Flume 進行統一的批處理和流處理編程。

關於統一模型的核心關鍵思考在於,儘管在當時我們也沒有深刻意識到,批流處理模型本質上沒有區別: 僅僅是在表和流的處理上有些小變化而已。正如我們在第 6 章中所討論到的,主要的區別僅僅是在將表上增量的變化轉換為流,其他一切在概念上是相同的。通過利用批處理和流處理兩者大量的共性需求,可以提供一套引擎,適配於兩套不同處理方式,這讓流計算系統更加易於使用。

除了利用批處理和流處理之間的系統共性之外,我們還仔細查看了多年來我們在 Google 中遇到的各種案例,並使用這些案例來研究統一模型下系統各個部分。我們研究主要內容如下:

  • 未對齊的事件時間窗口(如會話窗口),能夠簡明地表達這類複雜的分析,同時亦能處理亂序數據。
  • 自定義窗口支持,系統內置窗口很少適合所有業務場景,需要提供給用戶自定義窗口的能力。
  • 靈活的觸發和統計模式,能夠滿足正確性,延遲,成本的各項業務需求。
  • 使用 Watermark 來推斷輸入數據的完整性,這對於異常檢測等用例至關重要,其中異常檢測邏輯會根據是否缺少數據做出異常判斷。
  • 底層執行環境的邏輯抽象,無論是批處理,微批處理還是流式處理,都可以在執行引擎中提供靈活的選擇,並避免系統級別的參數設置(例如微批量大小)進入邏輯 API。

總之,這些平衡了靈活性,正確性,延遲和成本之間的關係,將 DataFlow 的模型應用於大量用戶業務案例之中。

考慮到我們之前整本書都在討論 DataFlow 和 Beam 模型的各類問題,我在此處重新給大家講述這些概念純屬多此一舉。但是,如果你正在尋找稍微更具學術性的內容以及一些應用案例,我推薦你看下 2015 年發表的《DataFlow 論文..》(圖 10-27)。

圖 10-27 DataFlow 的論文

DataFlow 還有不少可以大書特書的功能特點,但在這章內容構成來看,我認為 DataFlow 最重要的是構建了一套批流統一的大數據處理模型。DataFlow 為我們提供了一套全面的處理無界且無序數據集的能力,同時這套系統很好的平衡了正確性、延遲、成本之間的相互關係。


Flink

Flink(圖 10-28)在 2015 年突然出現在大數據舞台,然後似乎在一夜之間從一個無人所知的系統迅速轉變為人人皆知的流式處理引擎。

圖 10-28 Flink 的時間軸

在我看來,Flink 崛起有兩個主要原因:

  • 採用 Dataflow/Beam 編程模型,使其成為完備語義功能的開源流式處理系統。
  • 其高效的快照實現方式,源自 Chandy 和 Lamport 的原始論文《「Distributed Snapshots: Determining Global States of Distributed Systems」》的研究,這為其提供了正確性所需的強一致性保證。

Reuven 在第 5 章中簡要介紹了 Flink 的一致性機制,這裡在重申一下,其基本思想是在系統中的 Worker 之間沿著數據傳播路徑上產生周期性 Barrier。這些 Barrier 充當了在不同 Worker 之間傳輸數據時的對齊機制。當一個 Worker 在其所有上游運算元輸入來源(即來自其所有上游一層的 Worker)上接收到全部 Barrier 時,Worker 會將當前所有 key 對應的狀態寫入一個持久化存儲。這個過程意味著將這個 Barrier 之前的所有數據都做了持久化。

圖 10-29 Chandy-Lamport 快照

通過調整 Barrier 的生成頻率,可以間接調整 Checkpoint 的執行頻率,從而降低時延並最終獲取更高的吞吐(其原因是做 Checkpoint 過程中涉及到對外進行持久化數據,因此會有一定的 IO 導致延時)。

Flink 既能夠支持精確一次的語義處理保證,同時又能夠提供支持事件時間的處理能力,這讓 Flink 獲取的巨大的成功。接著, Jamie Grier 發表他的題為「《Extending the Yahoo! Streaming Benchmark》「(圖 10-30)的文章,文章中描述了 Flink 性能具體的測試數據。在那篇文章中,傑米描述了兩個令人印象深刻的特點:

  1. 構建一個用於測試的 Flink 數據管道,其擁有比 Twitter Storm 更高的準確性(歸功於 Flink 的強一次性語義),但成本卻降到了 1%。

圖 10-30。 《Extending the Yahoo! Streaming Benchmark》

2. Flink 在精確一次的處理語義參數設定下,仍然達到 Storm 的 7.5 倍吞吐量(而且,Storm 還不具備精確一次的處理語義)。此外,由於網路被打滿導致 Flink 的性能受到限制 ; 進一步消除網路瓶頸後 Flink 的吞吐量幾乎達到 Storm 的 40 倍。

從那時起,許多其他流式處理項目(特別是 Storm 和 Apex)都採用了類似演算法的數據處理一致性機制。

圖 10-31 《Savepoints: Turning Back Time》

通過快照機制,Flink 獲得了端到端數據一致性。Flink 更進了一步,利用其快照的全局特性,提供了從過去的任何一點重啟整個管道的能力,這一功能稱為 SavePoint(在 Fabian Hueske 和 Michael Winters 的帖子 [《Savepoints: Turning Back Time》(data-artisans.com/blog/)] 中有所描述,[圖 10-31])。Savepoints 功能參考了 Kafka 應用於流式傳輸層的持久化和可重放特性,並將其擴展應用到整個底層 Pipeline。流式處理仍然遺留大量開放性問題有待優化和提升,但 Flink 的 Savepoints 功能是朝著正確方向邁出的第一步,也是整個行業非常有特點的一步。 如果您有興趣了解有關 Flink 快照和保存點的系統構造的更多信息,請參閱《State Management in Apache Flink》(圖 10-32),論文詳細討論了相關的實現。

圖 10-32 《State Management in Apache Flink》

除了保存點之外,Flink 社區還在不斷創新,包括將第一個實用流式 SQL API 推向大規模分散式流處理引擎的領域,正如我們在第 8 章中所討論的那樣。 總之,Flink 的迅速崛起成為流計算領軍角色主要歸功於三個特點:

  1. 整合行業裡面現有的最佳想法(例如,成為第一個開源 DataFlow/Beam 模型)
  2. 創新性在表上做了大量優化,並將狀態管理髮揮更大價值,例如基於 Snapshot 的強一致性語義保證,Savepoints 以及流式 SQL。
  3. 迅速且持續地推動上述需求落地。

另外,所有這些改進都是在開源社區中完成的,我們可以看到為什麼 Flink 一直在不斷提高整個行業的流計算處理標準。


Beam

我們今天談到的最後一個系統是 Apache Beam(圖 10-33)。 Beam 與本章中的大多數其他系統的不同之處在於,它主要是編程模型,API 設計和可移植層,而不是帶有執行引擎的完整系統棧。但這正是我想強調的重點:正如 SQL 作為聲明性數據處理的通用語言一樣,Beam 的目標是成為程序化數據處理的通用語言。

圖 10-33 Apache Beam 的時間軸

具體而言,Beam 由許多組件組成:

  • 一個統一的批量加流式編程模型,繼承自 Google DataFlow 產品設計,以及我們在本書的大部分內容中討論的細節。該模型獨立於任何語言實現或 runtime 系統。您可以將此視為 Beam 等同於描述關係代數模型的 SQL。
  • 一組實現該模型的 SDK(軟體開發工具包),允許底層的 Pipeline 以不同 API 語言的慣用方式編排數據處理模型。 Beam 目前提供 Java,Python 和 Go 的 SDK,可以將它們視為 Beam 的 SQL 語言本身的程序化等價物。
  • 一組基於 SDK 的 DSL(特定於域的語言),提供專門的介面,以獨特的方式描述模型在不同領域的介面設計。SDK 來描述上述模型處理能力的全集,但 DSL 描述一些特定領域的處理邏輯。 Beam 目前提供了一個名為 Scio 的 Scala DSL 和一個 SQL DSL,它們都位於現有 Java SDK 之上。
  • 一組可以執行 Beam Pipeline 的執行引擎。執行引擎採用 Beam SDK 術語中描述的邏輯 Pipeline,並儘可能高效地將它們轉換為可以執行的物理計劃。目前,針對 Apex,Flink,Spark 和 Google Cloud Dataflow 存在對應的 Beam 引擎適配。在 SQL 術語中,您可以將這些引擎適配視為 Beam 在各種 SQL 資料庫的實現,例如 Postgres,MySQL,Oracle 等。

Beam 的核心愿景是實現一套可移植介面層,最引人注目的功能之一是它計劃支持完整的跨語言可移植性。儘管最終目標尚未完全完成(但即將面市),讓 Beam 在 SDK 和引擎適配之間提供足夠高效的抽象層,從而實現 SDK 和引擎適配之間的任意切換。我們暢想的是,用 JavaScript SDK 編寫的數據 Pipeline 可以在用 Haskell 編寫的引擎適配層上無縫地執行,即使 Haskell 編寫的引擎適配本身沒有執行 JavaScript 代碼的能力。

作為一個抽象層,Beam 如何定位自己和底層引擎關係,對於確保 Beam 實際為社區帶來價值至關重要,我們也不希望看到 Beam 引入一個不必要的抽象層。這裡的關鍵點是,Beam 的目標永遠不僅僅是其所有底層引擎功能的交集(類似最小公分母)或超集(類似廚房水槽)。相反,它旨在為整個社區大數據計算引擎提供最佳的想法指導。這裡面有兩個創新的角度:

  • Beam 本身的創新

Beam 將會提出一些 API,這些 API 需要底層 runtime 改造支持,並非所有底層引擎最初都支持這些功能。這沒關係,隨著時間的推移,我們希望許多底層引擎將這些功能融入未來版本中 ; 對於那些需要這些功能的業務案例來說,具備這些功能的引擎通常會被業務方選擇。

圖 10-34 《Powerful and modular I/O connec‐ tors with Splittable DoFn in Apache Beam》

這裡舉一個 Beam 裡面關於 SplittableDoFn 的 API 例子,這個 API 可以用來實現一個可組合的,可擴展的數據源。(具體參看 Eugene Kirpichov 在他的文章《 「Powerful and modular I/O connectors with Splittable DoFn in Apache Beam》中描述 [圖 10-34])。它設計確實很有特點且功能強大,目前我們還沒有看到所有底層引擎對動態負載均衡等一些更具創新性功能進行廣泛支持。然而,我們預計這些功能將隨著時間的推移而持續加入底層引擎支持的範圍。

  • 底層引擎的創新

底層引擎適配可能會引入底層引擎所獨特的功能,而 Beam 最初可能並未提供 API 支持。這沒關係,隨著時間的推移,已證明其有用性的引擎功能將在 Beam API 逐步實現。

這裡的一個例子是 Flink 中的狀態快照機制,或者我們之前討論過的 Savepoints。 Flink 仍然是唯一一個以這種方式支持快照的公開流處理系統,但是 Beam 提出了一個圍繞快照的 API 建議,因為我們相信數據 Pipeline 運行時優雅更新對於整個行業都至關重要。如果我們今天推出這樣的 API,Flink 將是唯一支持它的底層引擎系統。但同樣沒關係,這裡的重點是隨著時間的推移,整個行業將開始迎頭趕上,因為這些功能的價值會逐步為人所知。這些變化對每個人來說都是一件好事。

通過鼓勵 Beam 本身以及引擎的創新,我們希望推進整個行業快速演化,而不用再接受功能妥協。 通過實現跨執行引擎的可移植性承諾,我們希望將 Beam 建立為表達程序化數據處理流水線的通用語言,類似於當今 SQL 作為聲明性數據處理的通用處理方式。這是一個雄心勃勃的目標,我們並沒有完全實現這個計劃,到目前為止我們還有很長的路要走。

總 結

我們對數據處理技術的十五年發展進行了蜻蜓點水般的回顧,重點關注那些推動流式計算髮展的關鍵系統和關鍵思想。來,最後,我們再做一次總結:

  • MapReduce:可擴展性和簡單性 通過在強大且可擴展的執行引擎之上提供一組簡單的數據處理抽象,MapReduce 讓我們的數據工程師專註於他們的數據處理需求的業務邏輯,而不是去構建能夠適應在一大堆普通商用伺服器上的大規模分散式處理程序。
  • Hadoop:開源生態系統 通過構建一個關於 MapReduce 的開源平台,無意中創建了一個蓬勃發展的生態系統,其影響力所及的範圍遠遠超出了其最初 Hadoop 的範圍,每年有大量的創新性想法在 Hadoop 社區蓬勃發展。
  • Flume:管道及優化 通過將邏輯流水線操作的高級概念與智能優化器相結合,Flume 可以編寫簡潔且可維護的 Pipeline,其功能突破了 MapReduce 的 Map→Shuffle→Reduce 的限制,而不會犧牲性能。
  • Storm:弱一致性,低延遲 通過犧牲結果的正確性以減少延遲,Storm 為大眾帶來了流計算,並開創了 Lambda 架構的時代,其中弱一致的流處理引擎與強大一致的批處理系統一起運行,以實現真正的業務目標低延遲,最終一致型的結果。
  • Spark: 強一致性 通過利用強大一致的批處理引擎的重複運行來提供無界數據集的連續處理,Spark Streaming 證明至少對於有序數據集的情況,可以同時具有正確性和低延遲結果。
  • MillWheel:亂序處理 通過將強一致性、精確一次處理與用於推測時間的工具(如水印和定時器)相結合,MillWheel 做到了無序數據進行準確的流式處理。
  • Kafka: 持久化的流式存儲,流和表對偶性 通過將持久化數據日誌的概念應用於流傳輸問題,Kafka 支持了流式數據可重放功能。通過對流和表理論的概念進行推廣,闡明數據處理的概念基礎。
  • Cloud Dataflow:統一批流處理引擎 通過將 MillWheel 的無序流式處理與高階抽象、自動優化的 Flume 相結合,Cloud Dataflow 為批流數據處理提供了統一模型,並且靈活地平衡正確性、計算延遲、成本的關係。
  • Flink:開源流處理創新者 通過快速將無序流式數據處理的強大功能帶到開源世界,並將其與分散式快照及保存點功能等自身創新相結合,Flink 提高了開源流處理的業界標準並引領了當前流式處理創新趨勢。
  • Beam: 可移植性 通過提供整合行業最佳創意的強大抽象層,Beam 提供了一個可移植 API 抽象,其定位為與 SQL 提供的聲明性通用語言等效的程序介面,同時也鼓勵在整個行業中推進創新。

可以肯定的說,我在這裡強調的這 10 個項目及其成就的說明並沒有超出當前大數據的歷史發展。但是,它們對我來說是一系列重要且值得注意的大數據發展里程碑,它共同描繪了過去十五年中流處理演變的時間軸。自最早的 MapReduce 系統開始,儘管沿途有許多起伏波折,但不知不覺我們已經走出來很長一段征程。即便如此,在流式系統領域,未來我們仍然面臨著一系列的問題亟待解決。正所謂:路漫漫其修遠兮,吾將上下而求索。


譯者簡介

陳守元(花名:巴真),阿里巴巴高級產品專家。阿里巴巴實時計算團隊產品負責人,2010 年畢業即加入阿里集團參與淘寶數據平台建設,近 10 年的大數據從業經驗,開源項目 Alibaba DataX 發起人,當前負責阿里實時計算產品 Flink 的規劃與設計,致力於推動 Flink 成為下一代大數據處理標準。

《Streaming System》一書目前正由阿里巴巴實時計算團隊進行翻譯,預計今年年底上市,對流式系統感興趣的同學可以關注。


推薦閱讀:

TAG:大數據 | Spark | Hadoop |