RDD底層實現原理
RDD是一個分布式數據集,顧名思義,其數據應該分部存儲於多台機器上。事實上,每個RDD的數據都以Block的形式存儲於多台機器上,下圖是Spark的RDD存儲架構圖,其中每個Executor會啟動一個BlockManagerSlave,並管理一部分Block;而Block的元數據由Driver節點的BlockManagerMaster保存。BlockManagerSlave生成Block后向BlockManagerMaster注冊該Block,BlockManagerMaster管理RDD與Block的關系,當RDD不再需要存儲的時候,將向BlockManagerSlave發送指令刪除相應的Block。
圖2 RDD存儲原理
RDD cache的原理
RDD的轉換過程中,並不是每個RDD都會存儲,如果某個RDD會被重復使用,或者計算其代價很高,那么可以通過顯示調用RDD提供的cache()方法,把該RDD存儲下來。那RDD的cache是如何實現的呢?
RDD中提供的cache()方法只是簡單的把該RDD放到cache列表中。當RDD的iterator被調用時,通過CacheManager把RDD計算出來,並存儲到BlockManager中,下次獲取該RDD的數據時便可直接通過CacheManager從BlockManager讀出。
RDD dependency與DAG
RDD提供了許多轉換操作,每個轉換操作都會生成新的RDD,這是新的RDD便依賴於原有的RDD,這種RDD之間的依賴關系最終形成了DAG(Directed Acyclic Graph)。
RDD之間的依賴關系分為兩種,分別是NarrowDependency與ShuffleDependency,其中ShuffleDependency為子RDD的每個Partition都依賴於父RDD的所有Partition,而NarrowDependency則只依賴一個或部分的Partition。下圖的groupBy與join操作是ShuffleDependency,map和union是NarrowDependency。
圖3 RDD dependency
RDD partitioner與並行度
每個RDD都有Partitioner屬性,它決定了該RDD如何分區,當然Partition的個數還將決定每個Stage的Task個數。當前Spark需要應用設置Stage的並行Task個數(配置項為:spark.default.parallelism),在未設置的情況下,子RDD會根據父RDD的Partition決定,如map操作下子RDD的Partition與父Partition完全一致,Union操作時子RDD的Partition個數為父Partition個數之和。
如何設置spark.default.parallelism對用戶是一個挑戰,它會很大程度上決定Spark程序的性能。
參考:http://www.cnblogs.com/shenh062326/p/4130973.html