第2章
spark 程式設計模型
與hadoop相比,spark最初為提公升效能而誕生。spark是hadoop mapreduce的演化和改進,並相容了一些資料庫的基本思想,可以說,spark一開始就站在hadoop與資料庫這兩個巨人的肩膀上。同時,spark依靠scala強大的函式式程式設計actor通訊模式、閉包、容器、泛型,並借助統一資源排程框架,成為乙個簡潔、高效、強大的分布式大資料處理框架。
spark在運算期間,將輸入資料與中間計算結果儲存在記憶體中,直接在記憶體中計算。另外,使用者也可以將重複利用的資料快取在記憶體中,縮短資料讀寫時間,以提高下次計算的效率。顯而易見,spark基於記憶體計算的特性使其擅長於迭代式與互動式任務,但也不難發現,spark需要大量記憶體來完成計算任務。集群規模與spark效能之間呈正比關係,隨著集群中機器數量的增長,spark的效能也呈線性增長。接下來介紹spark程式設計模型。
2.1 rdd彈性分布式資料集
通常來講,資料處理有幾種常見模型:iterative algorithms、relational queries、map-
reduce、stream processing。例如,hadoop mapreduce採用了mapreduce模型,storm則採用了stream processing模型。
與許多其他大資料處理平台不同,spark建立在統一抽象的rdd之上,而rdd混合了上述這4種模型,使得spark能以基本一致的方式應對不同的大資料處理場景,包括mapreduce、streaming、sql、machine learning以及graph等。這契合了matei zaharia提出的原則:「設計乙個通用的程式設計抽象(unified programming abstraction)」,這也正是spark的魅力所在,因此要理解spark,先要理解rdd的概念。
2.1.1 rdd簡介
rdd(resilient distributed datasets,彈性分布式資料集)是乙個容錯的、並行的資料結構,可以讓使用者顯式地將資料儲存到磁碟或記憶體中,並控制資料的分割槽。rdd還提供了一組豐富的操作來操作這些資料,諸如map、flatmap、filter等轉換操作實現了monad模式,很好地契合了scala的集合操作。除此之外,rdd還提供諸如join、groupby、reducebykey等更為方便的操作,以支援常見的資料運算。
rdd是spark的核心資料結構,通過rdd的依賴關係形成spark的排程順序。所謂spark應用程式,本質是一組對rdd的操作。
下面介紹rdd的建立方式及操作運算元型別。
rdd的兩種建立方式
從檔案系統輸入(如hdfs)建立
從已存在的rdd轉換得到新的rdd
rdd的兩種操作運算元
transformation(變換)
transformation型別的運算元不是立刻執行,而是延遲執行。也就是說從乙個rdd變換為另乙個rdd的操作需要等到action操作觸發時,才會真正執行。
action(行動)
action型別的運算元會觸發spark提交作業,並將資料輸出到spark系統。
2.1.2 深入理解rdd
rdd從直觀上可以看作乙個陣列,本質上是邏輯分割槽記錄的集合。在集群中,乙個rdd可以包含多個分布在不同節點上的分割槽,每個分割槽是乙個dataset片段,如圖2-1所示。
在圖2-1中,rdd-1含有三個分割槽(p1、p2和p3),分布儲存在兩個節點上:node1與node2。rdd-2只有乙個分割槽p4,儲存在node3節點上。rdd-3含有兩個分割槽p5和p6,儲存在node4節點上。
1. rdd依賴
rdd可以相互依賴,如果rdd的每個分割槽最多只能被乙個child rdd的乙個分割槽使用,則稱之為窄依賴(narrow dependency);若多個child rdd分割槽都可以依賴,則稱之為寬依賴(wide dependency)。不同的操作依據其特性,可能會產生不同的依賴。例如,map操作會產生窄依賴,join操作則產生寬依賴,如圖2-2所示。
2. rdd支援容錯性
支援容錯通常採用兩種方式:日誌記錄或者資料複製。對於以資料為中心的系統而言,這兩種方式都非常昂貴,因為它需要跨集群網路拷貝大量資料。
rdd天生是支援容錯的。首先,它自身是乙個不變的(immutable)資料集,其次,rdd之間通過lineage產生依賴關係(在下章繼續**這個話題),因此rdd能夠記住構建它的操作圖,當執行任務的worker失敗時,完全可以通過操作圖獲得之前執行的操作,重新計算。因此無須採用replication方式支援容錯,很好地降低了跨網路的資料傳輸成本。
3. rdd的高效性
rdd提供了兩方面的特性:persistence(持久化)和partitioning(分割槽),使用者可以通過persist與partitionby函式來控制這兩個特性。rdd的分割槽特性與平行計算能力(rdd定義了parallerize函式),使得spark可以更好地利用可伸縮的硬體資源。如果將分割槽與持久化二者結合起來,就能更加高效地處理海量資料。
另外,rdd本質上是乙個記憶體資料集,在訪問rdd時,指標只會指向與操作相關的部分。例如,存在乙個面向列的資料結構,其中乙個實現為int型陣列,另乙個實現為float型陣列。如果只需要訪問int欄位,rdd的指標可以只訪問int陣列,避免掃瞄整個資料結構。
再者,如前文所述,rdd將操作分為兩類:transformation與action。無論執行了多少次transformation操作,rdd都不會真正執行運算,只有當action操作被執行時,運算才會觸發。而在rdd的內部實現機制中,底層介面則是基於迭代器的,從而使得資料訪問變得更高效,也避免了大量中間結果對記憶體的消耗。
2.1.3 rdd特性總結
rdd是spark的核心,也是整個spark的架構基礎。它的特性可以總結如下:
1) rdd是不變的(immutable)資料結構儲存。
2) rdd將資料儲存在記憶體中,從而提供了低延遲性。
3) rdd是支援跨集群的分布式資料結構。
4) rdd可以根據記錄的key對結構分割槽。
5) rdd提供了粗粒度的操作,並且都支援分割槽。
循序漸進學程式設計
軟體開發者是乙個日新月異的領域 it 中的大師,今天的程式設計方式與明天的程式設計或許截然不同,技術在不斷地革新,新語言 新平台的如雨後春筍般出現 更好的解決方案的冒出,因此我們需要跟得上節奏,我們沒有選擇,唯有努力提高自己。下面的幾點建議或許能幫助你成為乙個優秀地開發者。你是否聽說過 kaizen...
循序漸進學習Django
利用這一星期的業餘時間學習django,學到了模板系統,感覺還是不錯,很簡單的東東,django是個python web框架,即然是框架,就提供了很多已經封裝好的能夠快速解決問題的方法.所以忽然覺得太先進的框架反而對自己的python基礎發展不太好.即使學會了django提供的模板使用方法,但是不知...
《循序漸進學Docker》 導讀
致謝 首先要感謝dotcloud公司,是他們創立了docker這個容器引擎,同時也要感謝為docker整個生態圈貢獻大量周邊元件的所有作者,是你們讓docker技術發展得越來越好,開源的精神與力量在你們身上體現得淋漓盡致。感謝王冬生兄貢獻他在工作中的案例 docker離線系統應用案例 內容具有非常高...