天天看點

Spark RDDs(彈性分布式資料集):為記憶體中的叢集計算設計的容錯抽象第一節第二節第三節第四節第五節第六節第七節 第八節 第九節 

本文是閱讀《resilient distributed datasets: a fault-tolerant abstraction for in-memory cluster computing》過程中,抽了局部一些關注點翻譯出來的文章,沒有将全文都翻譯。希望這些碎片化甚至不通順的記錄,可以幫助讀者取代閱讀原論文。

論文位址http://www.cs.berkeley.edu/~matei/papers/2012/nsdi_spark.pdf

主要介紹了現有的叢集計算架構存在的問題,然後介紹了rdd的幾個設計亮點,對比了spark的不同之處和優勢點

解決現存疊代式算法和互動式資料挖掘倆問題 iterative algorithms and interactive data mining tools.

嚴格的記憶體分享,粗粒度而非細粒度 based on coarsegrained transformations rather than fine-grained updates to shared state

dryad 和 mr 是現有的叢集計算架構 他們能分布式 能容錯 但是沒能利用好分布式記憶體

導緻他們在多次利用中間資料的計算上不夠效率 

有很多疊代式機器學習和圖算法 pagerank k-means lr 

還有一點 就是幫助互動式資料挖掘

現有的解決計算之間(如兩個mr job下面)重用資料的方法 是存到一個外部分布式檔案系統裡

這帶來了很大的間接消耗在 資料備份,磁盤io,以及序列化 而這些主宰了執行時間

已經出現的針對這一問題的特殊架構:pregel 疊代式圖計算 把中間資料存記憶體  haloop提供疊代mr接口  

但他們隻針對一部分特殊計算元件,對資料分享做的很含蓄,沒有提供更抽象,通用的重用

rdd的一個原文定義:

rdds are fault-tolerant, parallel data structures that let users explicitly persist intermediate results in memory, control their partitioning to optimize data placement, and manipulate them using a rich set of operators.

介紹rdd

rdd是隻讀,分區記錄的集合

transformations:從現有的存儲檔案生成rdd或由别的rdd生成新rdd

rdd不用一直物化,他充分知道自己是怎麼被計算出來的,他的lineage血緣

persistence and partitioning 是rdd另兩個方面

持久化指使用者可以指定他們要哪個rdd,存儲政策是什麼

分區指使用者可以決定key來讓rdd分區在機器之間,這對于 位置優化(placement optimizations)很有用

spark程式設計api,對rdd進行的actions,如:count(),collect(),save()

且是懶式的,是以可以管道式變換 (pipeline transformations)

使用者可以持久化rdd,spark預設是放記憶體裡,ram不夠大就放磁盤上

使用者可以指定持久化政策,比如隻存硬碟上或在不同機器上複制,設定flag,最後使用者可以設定優先級,哪個記憶體裡的資料先放到硬碟上

rdd與分布式記憶體(dsm)的對比:

Spark RDDs(彈性分布式資料集):為記憶體中的叢集計算設計的容錯抽象第一節第二節第三節第四節第五節第六節第七節 第八節 第九節 

dsm是一個很通用的抽象,他的普遍性導緻了比較難實作容錯和高效

rdd不适合大塊的寫,但是更高效和容錯,且沒有檢查的開銷,因為可以借助血緣恢複,且丢失的分區在重新計算的時候,也是在不同節點上并行的,比復原整個程式快很多

對于大塊資料的操作,rdd會排程到本地資料執行,提高效率。資料太大就存硬碟。

rdd不支援的場景:

    rdd适合批處理,具體是對資料集裡所有元素進行同一個操作,這樣他執行轉換和恢複就很快,原因是不記錄大量log

    不适合異步細粒度更新,比如web引用的存儲和增量web爬蟲

spark程式設計接口

選用scala是因為他的簡明(互動式)和高效(靜态類型),而rdd并沒有函數式程式設計的需求

rdd是靜态類型對象

join适合key-value的rdd

Spark RDDs(彈性分布式資料集):為記憶體中的叢集計算設計的容錯抽象第一節第二節第三節第四節第五節第六節第七節 第八節 第九節 

拿邏輯回歸裡的梯度下降和pagerank,介紹了下疊代式計算的方式和rdd上的寫法

rdd的表示

如何表示rdd之間的依賴:窄依賴,一個父rdd最多被一個子rdd用(map);寬依賴,多個子rdd(join)

窄依賴:在一個叢集節點上管道式執行,計算所有父分區。如map->filter;錯誤恢複很高效

寬依賴:要求所有父分區可用,在所有節點上進行類mapreduce操作

Spark RDDs(彈性分布式資料集):為記憶體中的叢集計算設計的容錯抽象第一節第二節第三節第四節第五節第六節第七節 第八節 第九節 

實作

每個spark程式在mesos上是一個獨立的應用,有自己的驅動,worker以及mesos配置設定的共享資源

下面講幾個實作中的有趣部分:任務排程,允許互動式的spark解釋器,記憶體管理,檢查支援(checkpointing)

任務排程

spark的任務排程類似dryad

每當使用者進行一次action,首先會檢查rdd的血緣圖,建立一個stages的dag,按stage來執行這次action

每個stage都盡量包括盡可能多的管道式變換的窄依賴,stages之間的界限,就是寬依賴的洗操作,或者任何已經準備好了的分區。排程器就一個個執行這些stage,直到目标rdd生成出來

Spark RDDs(彈性分布式資料集):為記憶體中的叢集計算設計的容錯抽象第一節第二節第三節第四節第五節第六節第七節 第八節 第九節 

排程器布置任務是基于資料本地化配置設定的,采用延遲排程。

對于寬依賴,目前是物化中間結果在節點上,保持住父分區來簡化錯誤恢複,和mr的map outputs相似

任務失敗則重跑,如果丢失了如shuffle這樣的中間結果會重新計算,目前不容忍排程失敗

lookup操作提供随機通路元素,根據key在哈希分區上找

解釋器整合

在scala解釋器的基礎上,做了改變:

class shipping:讓工作節點通過http獲得class的bytecode

修改了的code generation邏輯:為了讓work節點能拿到引用,直接指向每行的執行個體(可能翻譯不準确,了解不是很到位)

記憶體管理

spark提供三種持久化rdd的存儲選擇:以反序列化java對象的方式存記憶體,以序列化資料的方式存記憶體,存磁盤

第一種最快,jvm可以本地化取rdd元素,第二種是高效記憶體化的方式

記憶體政策是lru,新的rdd不夠空間的時候,貫徹最近最少原則。同時,給予使用者對rdd“持久性優先級”的控制

目前rdd有自己單獨的記憶體空間,将來打算調研用一個統一的記憶體管理者在不同的執行個體之間分享式rdd

支援檢查(checkpointing, 翻譯為檢查可能不太妥當,見諒)

盡管從rdd錯誤恢複的時候會使用血緣,但如果血緣鍊很長,就會很耗時,是以有必要對一些rdd進行 穩定存儲時的檢查

是以是為了長血緣鍊提供的,比如pagerank,短的不值得。

api是persist裡的一個replicate flag,主導權在使用者手裡,也在調研自動化檢查。因為排程器知道每個資料集大小,第一次計算出來的耗時,是以應該可以做到優化最少恢複時間的選擇。

同時,rdd的隻讀特性有利于檢查,不需要中止和影響别的程式

評估

在疊代式機器學習和圖計算中,節省的主要耗時在于避免了io開銷和反序列化開銷

疊代式機器學習評估

kmeans和邏輯回歸,前者重在計算,後者重在反序列化和io開銷

spark在第一次之後的疊代中速度是非常快的。而在第一次疊代中,也稍快于hadoop,因為hadoop在master和slave之間的心跳機制

等等别的對比,以及已有的應用場景介紹

讨論

介紹了一些相關的系統

rdd的設計還有利于debug

相關工作

詳細歸類了各種類似系統

總結

(全文完)

繼續閱讀