穿針引線,進階必看——帶你盤點那些必知必會的Google經典大數據文論

何為大數據

“大數據”這個名字流行起來到現在,差不多已經有十年時間了。在這十年里,不同的人都按照自己的需要給大數據編出了自己的解釋。有些解釋很具體,來自于一線寫 Java 代碼的工程師,說用 Hadoop 處理數據就是大數據;有些解釋很高大上,來自于市場上靠發明大詞兒為生的演說家,說我們能采集和處理全量的數據就是大數據,如果只能采集到部分數據,或者處理的時候要對數據進行采樣,那就不是大數據。

在筆者看來,其實“大數據”技術的核心理念是非常清晰的,基本上可以被三個核心技術理念概括。

  1. 服務器規模:能夠伸縮到一千臺服務器以上的分布式數據處理集群的技術。

  2. 服務器架構:這個上千個節點的集群,是采用廉價的 PC 架構搭建起來的。

  3. 變成模式:“把數據中心當作是一臺計算機”(Datacenter as a Computer)。

出發問題 大數據技術 傳統數據處理技術 解決的問題
服務器規模 千臺服務器以上 幾十臺服務器 可行性
服務器架構 普通x86服務器,普通硬盤 專用硬件,如大型機、小型機 性價比
編程模型 Datacenter as a Computer 使用方自己處理分布式和容錯問題 復雜性

大型集群讓處理海量數據變得“可能”;基于開放的 PC 架構,讓處理海量數據變得“便宜”;而優秀的封裝和抽象,則是讓處理海量數據變得“容易”。這也是現在誰都能用上大數據技術的基礎。可以說,這三個核心技術理念,真正引爆了整個“大數據”技術,讓整個技術生態異常繁榮。

筆者認為,Google 能成為散播大數據火種的人,是有著歷史的必然性的:作為一個搜索引擎,Google 在數據層面,面臨著比任何一個互聯網公司都更大的挑戰。無論是 Amazon 這樣的電商公司,還是 Yahoo 這樣的門戶網站,都只需要存儲自己網站相關的數據。而 Google,則是需要抓取所有網站的網頁數據并存下來。而且光存下來還不夠,早在 1999 年,兩個創始人就發表了 PageRank 的論文,也就是說,Google 不只是簡單地根據網頁里面的關鍵字來排序搜索結果,而是要通過網頁之間的反向鏈接關系,進行很多輪的迭代計算,才能最終確認排序。而不斷增長的搜索請求量,讓 Google 還需要有響應迅速的在線服務。

三駕馬車和基礎設施

面對存儲、計算和在線服務這三個需求,Google 就在 2003、2004 以及 2006 年,分別拋出了三篇重磅論文。也就是我們常說的“大數據”的三駕馬車:GFSMapReduceBigtable

GFS 的論文發表于 2003 年,它主要是解決了數據的存儲問題。作為一個上千節點的分布式文件系統,Google 可以把所有需要的數據都能很容易地存儲下來。GFS它運行于廉價的普通硬件上,并提供容錯功能,和以往的文件系統的不同,系統中部件錯誤不再被當作異常,而是將其作為常見的情況加以處理。其的新穎之處并不在于它采用了多么令人驚訝的新技術,而在于它采用廉價的商用計算機集群構建分布式文件系統,在降低成本的同時經受了實際應用的考驗。

然后,光存下來還不夠,我們還要基于這些數據進行各種計算。這個時候,就輪到 2004 年發表的 MapReduce 出場了。通過借鑒 Lisp,Google 利用簡單的 MapReduce 兩個函數,對于海量數據計算做了一次抽象,這就讓“處理”數據的人,不再需要深入掌握分布式系統的開發了。而且他們推出的 PageRank 算法,也可以通過多輪的 MapReduce 的迭代來實現。

這樣,無論是 GFS 存儲數據,還是 MapReduce 處理數據,系統的吞吐量都沒有問題了,因為所有的數據都是順序讀寫。但是這兩個,其實都沒有辦法解決好數據的高性能隨機讀寫問題。

因此,面對這個問題,2006 年發表的 Bigtable 就站上了歷史舞臺了。它是直接使用 GFS 作為底層存儲,來做好集群的分片調度,以及利用 MemTable + SSTable 的底層存儲格式,來解決大集群、機械硬盤下的高性能的隨機讀寫問題。

Google 三駕馬車.png

到這里,GFSMapReduceBigtable 這三駕馬車的論文,就完成了“存儲”、“計算”、“實時服務”這三個核心架構的設計。不過這三篇論文其實還依賴了兩個基礎設施。

  • 了保障數據一致性的分布式鎖。對于這個問題,Google 在發表 Bigtable 的同一年,就發表了實現了 Paxos 算法的 Chubby 鎖服務的論文。

  • 數據怎么序列化以及分布式系統之間怎么通信。Google 在前面的論文里都沒有提到這一點,但是Facebook 在 2007 年發表的 Thrift 的相關論文解決了相關問題。

實際上,Bigtable 的開源實現 HBase,就用了 Thrift 作為和外部多語言進行通信的協議。Twitter 也開源了 elephant-bird,使得 Hadoop 上的 MapReduce 可以方便地使用 Thrift 來進行數據的序列化。

分布式系統的基建.png

OLAP 和 OLTP 數據庫

可以說,Google這三駕馬車是為整個業界帶來了大數據的火種,但是整個大數據領域的進化才剛剛開始。

首先 MapReduce,作為一個“計算”引擎,在有著更大計算需求的背景下(OLAP),其開始朝著以下方式進化。

  1. 編程模型MapReduce 的編程模型還是需要工程師去寫程序的,所以它進化的方向就是通過一門 DSL,進一步降低寫 MapReduce 的門檻。在這個領域的第一階段最終勝出的,是 Facebook 在 2009 年發表的 Hive。Hive 通過一門基本上和 SQL 差不多的 HQL,大大降低了數據處理的門檻,從而成為了大數據數據倉庫的事實標準;
  2. 執行引擎。Hive 雖然披上了一個 SQL 的皮,但是它的底層仍然是一個個的 MapReduce 的任務,所以延時很高,沒法當成一個交互式系統來給數據分析師使用。于是 Google 又在 2010 年,發表了 Dremel 這個交互式查詢引擎的論文,采用數據列存儲 + 并行數據庫的方式。這樣一來,Dremel 不僅有了一個 SQL 的皮,還進一步把 MapReduce 這個執行引擎給替換掉了。
  3. 多輪迭代問題:在 MapReduce 這個模型里,一個 MapReduce 就要讀寫一次硬盤,這對硬盤是無比大的負擔。2010年的Spark論文,通過把數據放在內存而不是硬盤里,大大提升了分布式數據計算性能。

圍繞 MapReduce,整個技術圈都在不斷優化和迭代計算性能,HiveDremelSpark 分別從“更容易寫程序”,“查詢響應更快”,“更快的單輪和多輪迭代”的角度,完成了對 MapReduce 的徹底進化。

作為一個“在線服務”的數據庫,Bigtable 的進化是這樣的:

  1. 事務問題和 Schema 問題:Google 先是在 2011 年發表了 Megastore 的論文,在 Bigtable 之上,實現了類 SQL 的接口,提供了 Schema,以及簡單的跨行事務。如果說 Bigtable 為了伸縮性,放棄了關系型數據庫的種種特性。那么 Megastore 就是開始在 Bigtable 上逐步彌補關系型數據庫的特性。
  2. 異地多活和跨數據中心問題:Google 在 2012 年發表的 Spanner,能夠做到“全局一致性”。這樣,就算是基本解決了這兩個問題,第一次讓我們有一個“全球數據庫”。
大數據系統演進.png

本質上樹,MapReduce 的迭代是在不斷優化OLAP類型的數據處理性能,而Bigtable的進化,則是在保障伸縮性的前提下,獲得了更多的關系型數據庫的能力

如果對OLAP的技術演化有興趣,可以參見作者前文 技術爭鳴——關于OLAP引擎你所需要知道的一切

實時數據處理的抽象進化

MapReduceDremel,我們查詢數據的響應時間就大大縮短了。但是計算的數據仍然是固定的、預先確定的數據,這樣系統往往有著大到數小時、小到幾分鐘的數據延時。所以,為了解決好這個問題,流式數據處理就走上了舞臺。

首先是 Yahoo 在 2010 年發表了 S4 的論文并將其開源。而幾乎是在同一時間,Twitter 工程師南森·馬茨(Nathan Marz)以一己之力開源了 Storm,并且在很長一段時間成為了工業界的事實標準。和 GFS 一樣,Storm 還支持“至少一次”(At-Least-Once)的數據處理。另外,基于 StormMapReduce,南森更是提出了 Lambda 架構,它可以稱之為是第一個“流批協同”的大數據處理架構。

接著在 2011 年,Kafka的論文也發表了。最早的 Kafka 其實只是一個“消息隊列”,但是由于 Kafka 里發送的消息可以做到“正好一次”(Exactly-Once),所以大家就動起了在上面直接解決 Storm 解決不好的消息重復問題的念頭。于是,Kafka 逐步進化出了 Kafka Streams 這樣的實時數據處理方案。而后在 2014 年,Kafka 的作者 Jay Krepson 提出了 Kappa 架構,這個可以被稱之為第一代“流批一體”的大數據處理架構。

在大數據的流式處理似領域,乎沒有 Google 什么事兒,但是在 2015 年,Google 發表的 Dataflow 的模型,可以說是對于流式數據處理模型做出了最好的總結和抽象。一直到現在,Dataflow 就成為了真正的“流批一體”的大數據處理架構。而后來開源的 FlinkApache Beam,則是完全按照 Dataflow 的模型實現的了。

實時數據處理的演進過程.png

一致性與調度

到了現在,隨著“大數據領域”本身的高速發展,數據中心里面的服務器越來越多,我們對于數據一致性的要求也越來越高。為了解決一致性問題,我們就有了基于 Paxos 協議的分布式鎖。但是 Paxos 協議的性能很差,于是有了進一步的 Multi-Paxos 協議。可惜的是Paxos 協議并不容易理解,于是就有了 Raft 這個更容易理解的算法的出現。Kubernetes 依賴的 etcd 就是用 Raft 協議實現的。

也正是因為數據中心里面的服務器越來越多,我們會發現原有的系統部署方式越來越浪費。當我們有數百乃至數千臺服務器的時候,浪費的硬件和電力成本就成為不能承受之重了。于是,盡可能用滿硬件資源成為了剛需。由此一來,我們對于整個分布式系統的視角,也從虛擬機轉向了容器,這也是 Kubernetes 這個系統的由來。其從更加全面的角度來進行資源管理和調度系統。

如果想了解更多K8s的技術細節,可以參見作者前文 Kubernetes核心技術剖析和落地經驗

爭論與分歧

到此為止,筆者為大家簡答地介紹了大數據技術的論文演進的脈絡。但是整個技術的發展也并不是一個直線上升的狀態:

  • 有爭論,比如 MapReduce 的論文發表之后,數據庫領域知名的科學家大衛·德維特(David DeWitt)就發表過一篇論文“MapReduce:A major step backwards”,抨擊 MapReduce 相比于并行數據庫是一種倒退

  • 有妥協,比如,Bigtable 不支持跨行事務也不支持 SQL,就是一個明證。直到 5 年后發表的 Megastore,他們才開始著手解決這兩個問題;

  • 更有不成功的嘗試,典型的就是 SawzallPig,Google 在發表 MapReduce 論文之前,就發表了 Sawzall 這個用來撰寫 MapReduce 任務的 DSL,Yahoo 也很早就完成了對應的開源實現 Apache Pig。但是 10 年后的今天,我們的主流選擇是用 SQL 或者 DataFrame,Pig 的用戶已經不多了,而 Sawzall 也沒有再聽 Google 提起過。

所以可以說,大數據技術的發展是一個非常典型的技術工程的發展過程,跟隨這個脈絡,我們可以看到工程師們對于技術的探索、選擇過程,以及最終歷史告訴我們什么是正確的選擇。

大數據技術盤點

相比于某一門計算機課程、某一門編程語言或者某一個開源框架,“大數據”涉及到的知識點多而繁雜。所以這里,筆者就整理了一份知識地圖,好讓讀者可以對論文中及到的知識點有跡可循。

大數據技術布局.png

分布式系統

所有的大數據系統都是分布式系統。我們需要大數據系統,就是因為普通的單機已經無法滿足我們期望的性能了。那么作為一個分布式的數據系統,它就需要滿足三個特性:可靠性可擴展性可維護性

  • 可靠性:如果只記錄一份數據,那么當硬件故障的時候就會遇到丟數據的問題,所以我們需要對數據做復制。而數據復制之后,以哪一份數據為準,又給我們帶來了主從架構、多主架構以及無主架構的選擇。在最常見的主從架構里,根據復制過程,可以有同步復制和異步復制之分。同步復制的節點可以作為高可用切換的 Backup Master,而異步復制的節點只適合作為只讀的 Shadow Master。

  • 可擴展性:在“大數據”的場景下,單個節點存不下所有數據,于是就有了數據分區。常見的分區方式有兩種,第一種是通過區間進行分片,典型的代表就是 Bigtable,第二種是通過哈希進行分區,在大型分布式系統中常用的是一致性 Hash,典型的代表是 Cassandra。

  • 可維護性。我們需要考慮容錯,在硬件出現故障的時候系統仍然能夠運作。我們還需要考慮恢復,也就是當系統出現故障的時候,仍能快速恢復到可以使用的狀態。而為了確保我們不會因為部分網絡的中斷導致作出錯誤的判斷,我們就需要利用共識算法,來確保系統中能夠對哪個節點正在正常服務作出判斷。這也就引出了 CAP 這個所謂的“不可能三角”。

    分布式系統的核心問題就是 CAP 這個不可能三角,我們需要在一致性、可用性和分區容錯性之間做權衡和選擇。因此,我們選擇的主從架構、復制策略、分片策略,以及容錯和恢復方案,都是根據我們實際的應用場景下對于 CAP 進行的權衡和選擇。

存儲引擎

上萬臺的分布式集群,最終還是要落到每一臺單個服務器上完成數據的讀寫。那么在存儲引擎上,關鍵的技術點主要包括三個部分。

  • 事務。在傳統的數據庫領域,我們有 ACID 這樣的事務特性即原子性(Atomic)、一致性(Consistency)、隔離性(Isolation)以及持久性(Durability)。而在大數據領域,很多時候因為分布式的存在,事務常常會退化到 BASE 的模型,即表著基本可用(Basically Available)、軟狀態(Soft State)以及最終一致性(Eventually Consistent)。不過無論是 ACID 還是 BASE,在單機上,我們都會使用預寫日志(WAL)、快照(Snapshot)和檢查點(Checkpoints)以及寫時復制(Copy-on-Write)這些技術,來保障數據在單個節點的寫入是原子的。而只要寫入的數據記錄是在單個分片上,我們就可以保障數據寫入的事務性,所以我們很容易可以做到單行事務,或者是進一步的實體組(Entity Group)層面的事務。
  • 寫入和存儲。這個既要考慮到計算機硬件的特性,比如數據的順序讀寫比隨機讀寫快,在內存上讀寫比硬盤上快;也要考慮到我們在算法和數據結構中的時空復雜度,比如 Hash 表的時間復雜度是 O(1),B+ 樹的時間復雜度是 O(logN)。這樣,通過結合硬件性能、數據結構和算法特性,我們會看到分布式數據庫最常使用的,其實是基于 LSM 樹(Log-Structured Merge Tree)的 MemTable+SSTable 的解決方案。
  • 數據的序列化。 出于存儲空間和兼容性的考慮,我們會選用 Thrift 這樣的二進制序列化方案。而為了在分析數據的時候盡量減少硬盤吞吐量,我們則要研究 Parquet 或者 ORCFile 這樣的列存儲格式。然后,為了在 CPU、網絡和硬盤的使用上取得平衡,我們又會選擇 Snappy 或者 LZO 這樣的快速壓縮算法。

計算引擎

計算的維度實際上也是大數據領域本身進化和迭代最快的一部分。

  • 期初,最原始粗糙的 MapReduce 來進行批數據處理,然后圍繞它不斷迭代出了讓數據處理更快的 Spark 和讓數據處理更容易的各種 DSL(比如Hive)。
  • 然后,圍繞著實時數據處理,有了“最少一次”的 S4/Storm,并把它和批處理綜合到一起,產生了著名的 Lambda 架構。
  • 緊接著有了“以批為流”,通過 Mini-Batch 來進行實時數據處理的 Spark Streaming,以及“流批一體”,能夠做到“正好一次”的 Kafka 和 Kappa 結構。
  • 最后,還是 Google 一錘定音,給出了統一的 Dataflow 模型,并伴隨著有了 Apache Flink 和 Apache Beam 這兩個開源項目。

隨著 Dataflow 論文的發表,整個大數據的處理引擎逐漸收斂成了一個統一的模型,這是大數據領域發展的一個新的里程碑。

經典文章總結

最后,筆者把文中提到的這些論文的前后之間的脈絡聯系專門做了一張圖,放在了下面。如果讀者對某一篇論文感到困惑的時候,就可以去翻看它前后對應的論文,找到對應問題的來龍去脈。

論文體系.png

另外,如果有讀者覺得本文的內還不夠過癮,筆者強烈推薦你可以讀一下Big Data: A Survey這篇綜述文章,可以讓讀者更加深入“大數據”技術的全貌。

有的讀者可能擔心如何找到和下載這些論文。筆者已經貼心的為大家收集好了全部論文并上傳到云盤中,只要點擊下方連接,即可獲得全套經典論文。

鏈接: https://pan.baidu.com/s/1h9eoDbgIYZMeQKb1zDAPOw 提取碼: 4mei

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容