1、spark的一大特性就是基於記憶體計算,Driver只保存任務的巨集觀性的元數據,數據量較小,且在執行過程中基本不變,不做重點分析,而真正的計算任務Task分佈在各個Executor中,其中的記憶體數據量大,且會隨著計算的進行會發生實時變化,所以Executor的記憶體管理才分析的重點。 2、在執行Sp ...
1、spark的一大特性就是基於記憶體計算,Driver只保存任務的巨集觀性的元數據,數據量較小,且在執行過程中基本不變,不做重點分析,而真正的計算任務Task分佈在各個Executor中,其中的記憶體數據量大,且會隨著計算的進行會發生實時變化,所以Executor的記憶體管理才分析的重點。
2、在執行Spark應用程式時,集群會啟動Driver和Executor兩種JVM進程,前者為主控進程,負責創建spark上下文(context),提交spark作業(job),將作業轉化為計算任務(task),在各個Executor進程間協調任務的調度。後者負責在工作節點上執行具體任務,並將結果返回給Driver,同時為需要持久化的RDD提供存儲功能。
3、作為一個JVM進程,Executor的記憶體管理時基於JVM記憶體管理機制的,spark對JVM-on-heap記憶體進行了更為詳細的規劃,以充分利用。同時spark還引入了off-heap記憶體,使之可以直接從運行節點的系統記憶體中開闢空間,進一步優化記憶體的使用。
【堆記憶體的分配和回收完全依賴JVM的gc機制,應用不能靈活的操作記憶體,使用堆外記憶體則可以通過OS來分配和釋放,較為靈活】
早期靜態記憶體管理:on-heap分為四個區域,分別是Storage(20%)、Execution(60%)、Other(20%)、Ext,Storage用於緩存持久化的RDD數據和廣播變數等,Execution用於緩存shuffle過程中產生的中間數據,Other區用於存儲運行中的其他對象,Ext是一塊較小的預留空間,用以防止OOM的發生,起到兜底作用,幾個區塊間有嚴格的界限,不可逾越。off-heap分為兩個區,Storage(50%)、Execution(50%),也有嚴格界限,不可逾越。
spark1.6後引入統一記憶體管理:與靜態管理機制的不同在於初始Storage(50%)、Execution(50%),在執行過程中兩個區域可以根據自己和對方的內粗餘量彈性的越界分配,更加靈活高效。off-heap也是兩個區域,沒有嚴格界限可以動態占用。
4、記憶體的動態占用:
0.存儲 < 50% && 執行 < 50%:互不占用
1.存儲 > 50% && 執行 > 50%:溢寫磁碟(前提是緩存級別包含磁碟,若級別為純記憶體則丟棄數據)
2.存儲 > 50% && 執行 < 50%:存儲跨界借用,若一段時間後執行記憶體不足,則刪除被借用記憶體,優先滿足執行的記憶體需要。
3.存儲 < 50% && 執行 > 50%:執行跨界借用,若一段時間後存儲記憶體不足,則不能被執行占用的存儲區記憶體,因為執行的優先順序更高,要優先保證執行數據。
***
5、統一記憶體管理機制,有效的提高了堆記憶體和堆外記憶體的使用效率,降低了使用複雜度,但是並不能就此高枕無憂。由於RDD數據往往是長期生存的,如果存儲在記憶體中的數據過多,會引發頻繁的full-gc,降低了程式的吞吐量。