Spark:超越Hadoop MapReduce
引言:和 Hadoop 一樣,Spark 提供了一個 Map/Reduce API(分布式計算)和分布式存儲。二者主要的不同點是,Spark 在集群的內存中保存數據,而 Hadoop 在集群的磁盤中存儲數據。
本文選自《SparkGraphX實戰》。
大數據對一些數據科學團隊來說是 主要的挑戰,因為在要求的可擴展性方麵單機沒有能力和容量來運行大規模數據處 理。此外,即使專為大數據設計的係統,如 Hadoop,由於一些數據的屬性問題也很難有效地處理圖數據,我們將在本章的其他部分看到這方麵的內容。
Apache Spark 與 Hadoop 類似,數據分布式存儲在服務器的集群或者是“節點”上。 不同的是,Spark 將數據保存在內存(RAM)中,Hadoop 把數據保存在磁盤(機械 硬盤或者 SSD 固態硬盤)中。
定義 :在圖和集群計算方麵,“節點”這個詞有兩種截然不同的意思。 圖數據由頂點和邊組成,在這裏“節點”與頂點的意思相近。在集群計算 方麵,組成集群的物理機器也被稱為“節點”。為避免混淆,我們稱圖的 節點為頂點,這也是 Spark 中的專有名詞。而本書中的“節點”這個詞我 們嚴格定義為集群中的單個物理計算節點。
大數據因為數據量大單機無法處理。Hadoop 和 Spark 都是把數據分布在集群節點上的分 布式框架中。Spark 把分布式數據集存放在內存中,所以比 Hadoop 把數據存放在磁盤中 處理速度要快很多。
除了將要計算的數據保存的位置不同(內存和磁盤),Spark 的 API 比 Hadoop的 Map/Reduce API 更容易使用。Spark 使用簡潔且表達力較好的 Scala 作為原生編程語言,寫 Hadoop Map/Reduce 的 Java 代碼行數與寫 Spark 的 Scala 的代碼行的數 量比一般是 10:1。
雖然本書主要使用 Scala,但是你對 Scala 不熟悉也不用擔心,我們在第 3 章提 供了快速入門,包括怪異、晦澀和簡練的 Scala 語法。進一步熟悉 Java、C++、C#、 Python 等至少一門編程語言是必要的。
模煳的大數據定義
現在的“大數據”概念已經被很大程度地誇大了。大數據的概念可以追溯到Google 在 2003 年發表的 Google 文件係統的論文和 2004 年發表的 Map/Reduce 論文。
大數據這個術語有多種不同的定義,並且有些定義已經失去了大數據所應有的意 義。但是簡單的核心且至關重要的意義是:大數據是因數據本身太大,單機無法處理。
數據量已經呈爆炸性增長。數據來自網站的點擊、服務器日誌和帶有傳感器的 硬件等,這些稱為數據源。有些數據是圖數據(graph data),意味著由邊和頂點組成, 如一些協作類網站(屬於“Web 2.0”的社交媒體的一種)。大的圖數據集實際上是 眾包的,例如知識互相連接的 Wikipedia、Facebook 的朋友數據、LinkedIn 的連接數 據,或者 Twitter 的粉絲數據。
Hadoop :Spark 之前的世界
在討論 Spark 之前,我們總結一下 Hadoop 是如何解決大數據問題的,因為Spark 是建立在下麵將要描述的核心 Hadoop 概念之上的。
Hadoop 提供了在集群機器中實現容錯、並行處理的框架。Hadoop 有兩個關鍵 能力 :
- HDFS—分布式存儲
- MapReduce—分布式計算
HDFS 提供了分布式、容錯存儲。NameNode 把單個大文件分割成小塊,典型 的塊大小是 64MB 或 128MB。這些小塊文件被分散在集群中的不同機器上。容錯性 是將每個文件的小塊複製到一定數量的機器節點上(默認複製到 3 個不同節點, 下圖中為了表示方便,將複製數設置為 2)。假如一個機器節點失效,致使這個機器上的 所有文件塊不可用,但其他機器節點可以提供缺失的文件塊。這是 Hadoop 架構的 關鍵理念 :機器出故障是正常運作的一部分。
三個分布式數據塊通過 Hadoop 分布式文件係統(HDFS)保持兩個副本。
MapReduce 是提供並行和分布式計算的 Hadoop 並行處理框架,如下圖 。
MapReduce 是被 Hadoop 和 Spark 都用到的一個數據處理範式。圖中表示計算服務器日 誌文件中“error”出現的次數,這是一個 MapReduce 操作。通常 Map 操作是一對一的 操作,對每一個源數據項生成一個相應的數據轉換操作。Reduce 是多對一的操作,聚合 Map 階段的輸出。Hadoop 和 Spark 都用到了 MapReduce 範式。
用 MapReduce 框架,程序員寫一個封裝有 map 和 reduce 函數的獨立代碼片段來處 理 HDFS 上的數據集。為取到數據位置,代碼打包(jar 格式)分發到數據節點, Map 操作就在這些數據節點上執行,這避免了集群的數據傳輸導致消耗網絡帶寬。 對於 Reduce 聚合操作,Map 的結果被傳輸到多個 Reduce 節點上做 reduce 操作(稱 之為 shuffling)。首先,Map 階段是並行操作的,Hadoop 提供了一個彈性機製,當 一個機器節點或者一個處理過程失敗時,計算會在其他機器節點上重啟。
MapReduce 編程框架將數據集抽象為流式 key-value 鍵值對,然後處理這些鍵 值對並寫回到 HDFS。這是一個有局限的範式,但它已被用來解決許多數據並行問題, 用鏈接在一起的 MapReduce 進行“讀-處理-寫”操作過程。對於一些簡單的任務,上圖顯示的是比較適合的場景。但是對於一些如機器學習算法中的迭代計算算 法,用這種 MapReduce 範式就很痛苦,這也是選擇使用 Spark 的原因。
Spark :內存中的 MapReduce 處理
我們來看另一個可選的分布式處理係統,構建在 Hadoop 基礎之上的 Spark。在這一小節你會了解到,在 Spark 處理圖數據時扮演重要角色的彈性分 布式數據集(RDD)導致 Hadoop 衰落的兩類問題是 :
- 交互式查詢
- 迭代算法
Hadoop 很適合在一個大的數據集上做單次查詢,而在許多實際場景中,一旦有 了一個想要的答案,我們就想再問數據一個問題,這就是交互式查詢。使用 Hadoop 的話,就意味著要等待重新從磁盤中加載數據,再次處理數據。我們不得不執行一 組相同的計算作為隨後分析的前提,這不符合常理。
迭代算法已經被廣泛應用於機器學習任務,如隨機梯度下降算法,以及之後 會看到的 PageRank 這類圖計算算法。迭代算法是在一個數據集上一遍又一遍地做 一組計算,直到滿足一個標準(循環結束條件)才結束迭代。 在 Hadoop 中實現這種算法,一般需要一係列加載數據的 MapReduce 任務,這些 MapReduce 任務要在 每一個迭代過程中重複運行。對於非常大的數據集,每個迭代過程要花費 100 秒或1000 秒,整個迭代過程非常耗時。
下麵你會看到 Spark 如何解決這些問題。如 Hadoop 一樣,Spark 也是運行在 一個常見的硬件配置的機器集群上。Spark 中的一個核心抽象是彈性分布式數據集(RDD)。RDD 是由 Spark 應用創建的(在Spark Driver上),由集群管理,如下圖。
Spark 提供一個彈性分布式數據集,可以認為它是一個分布式的常駐內存的數組。
組成 RDD 分布式數據集的數據分區會被加載到集群的機器上。
基於內存的數據處理
Spark 執行的大部分操作都是在隨機訪問內存中(RAM)進行。Spark 是基於內 存的,而 Hadoop Map/Reduce 是順序處理數據,所以 Spark 比 Hadoop 更適合處理 隨機訪問的圖數據。
Spark 的關鍵好處在於交互式查詢和迭代處理過程中在內存中緩存 RDD。緩存 起來的 RDD 可以避免每次重新處理父 RDD 鏈,而隻需要直接返回父 RDD 計算後 的緩存結果。
自然的,這意味著要用到 Spark 的基於內存的計算處理特性,要求集群中的機 器內存要足夠大。要是可用內存不夠,那麼 Spark 就會優雅地溢出數據到磁盤,以 保證 Spark 能繼續運行。
當然 Spark 集群也需要一個持久化存儲數據的地方,而且還要是分布式存儲係 統才行,可選的有 HDFS、Cassandra 和亞馬遜的 S3。
本文選自《Spark GraphX實戰》,點此鏈接可在博文視點官網查看此書。
想及時獲得更多精彩文章,可在微信中搜索“博文視點”或者掃描下方二維碼並關注。
最後更新:2017-04-12 12:30:31