1 基本概念
Spark 是基於記憶體計算的大資料平行計算框架。 Spark 基於記憶體計算,提高了在大資料環境下資料處理的實時性,同時保證了高容錯性和高可伸縮性,允許使用者將 Spark 部署在大量廉價硬體之上,形成叢集。正是如此, Spark 工作機制也是圍繞這幾點開展,主要包括排程管理、記憶體管理、容錯機制。
3 Spark 工作機制介紹3.1 排程管理Spark 排程管理按照場景可以分為兩類,一類是 Spark 程式之間的排程,這是最主要的排程場景;另外一類是 Spark 程式內部的排程。
l Spark 程式之間的排程
當多個使用者提交多個 Spark 程式時, Spark 是如何排程這些應用併合理地分配資源呢?
Standalone 模式下,預設使用 FIFO ,每個 app 會獨佔所有資源,可以通過以下幾個引數調整叢集相關的資源:
1) spark.cores.max :調整 app 可以在整個叢集中申請的 CPU core 數量
2) spark.deploy.defaultCores :預設的 CPU core 數量
3) spark.executor.memory :限制每個 Executor 可用的記憶體
Mesos 模式下,可以使用
1) spark.mesos.coarse=true 設定靜態配置資源的策略
2) 使用 mesos://URL 且不配置 spark.mesos.coarse=true (每個 app 會有獨立固定的記憶體分配,空閒時其他機器可以使用其資源)
在 Yarn 模式下,提交作業時可以使用
1) 通過– num-executors 控制分配多少個 Executor 給 app
2) – executor-memory 和– executor-cores 分別控制 Executor 的記憶體和 CPU core
l Spark 程式內部的 Job 排程機制
一個程式應用中,由各個 Action 觸發的多個 Job 之間也是存在排程關係的。 Action 操作實現上是呼叫了 SparkContext 的 runJob 方法提交 Job 。
Spark 中排程 Job 有兩種策略
FIFO :
1) 第一個 Job 分配其所需的所有資源
2) 第二個 Job 如果還有剩餘資源的話就分配,否則等待
FAIR :
1) 使用輪詢的方式排程 Job
2) 可以通過配置 spark.scheduler.mode 調整 Job 的排程方式,也可以配置排程池。
其中排程池的配置如下:
n schedulingMode : FIFO 或者 FAIR
n weight :用於控制排程池相對於其他排程池的權重
n minShare :最小資源值 ( core 的數量 )
3.2 記憶體管理相比 Hadoop MapReduce , Spark 計算具有巨大的效能優勢,其中很大一部分是因為 Spark 對於記憶體的充分利用,以及提供的快取機制。
l 序列化
序列化的本質就是將物件轉換為位元組流,可以理解為將連結串列中儲存的非連續空間的資料儲存轉化為連續空間儲存的陣列中。
Spark 進行序列化操作後,記憶體或磁碟中 RDD 會含有物件的儲存,而在節點間資料的傳輸時,序列化之後的資料可以節約空間和提高效率。
l 壓縮
壓縮是日常生活中的一個常見操作,好處顯而易見,節約空間,從而就可以獲得時間 上的效率。 Spark 中序列化之後的資料可以進行壓縮以減少空間開銷。
Spark 支援兩種壓縮演算法,在不同的場景中選擇不同的壓縮演算法可以有效的提高程式執行的效率:
n Snappy 演算法:高壓縮速度
n LZF 演算法:高壓縮比
l 塊管理
RDD 從物理上看是一個元資料結構,記錄著 Block 和 Node 之間的對映關係。
儲存 RDD 是以 Block 塊為單位的,每個分割槽對應一個塊, PartitionID 通過元資料資訊可以對映到 Block 。 Spark 保證了每一個 RDD 都可以被重新恢復, RDD 的持久化由 Spark 的 Storage 模組負責,實現了 RDD 與物理儲存的解耦合。 Storage 模組負責管理 Spark 在計算過程中產生的資料,將那些在記憶體或磁碟、在本地或遠端存取資料的功能封裝了起來。
3.3 容錯機制Spark 以前的叢集容錯處理模型,像 MapReduce ,將計算轉換為一個有向無環圖( DAG )的任務集合,這樣可以通過重複執行 DAG 裡的一部分任務來完成容錯恢復。但是由於主要的資料儲存在分散式檔案系統中,沒有提供其他儲存的概念,容錯過程中需要在網路上進行資料複製,從而增加了大量的消耗。所以,分散式程式設計中經常需要做檢查點,即將某個時機的中間資料寫到儲存(通常是分散式檔案系統)中。
RDD 也是一個 DAG ,每一個 RDD 都會記住建立該資料集需要哪些操作,跟蹤記錄 RDD 的繼承關係,這個關係在 Spark 裡面叫 lineage 。由於建立 RDD 的操作是相對粗粒度的變換,即單一的操作應用於許多資料元素,而不需儲存真正的資料。當一個 RDD 的某個分割槽丟失時, RDD 有足夠的資訊記錄其如何通過其他 RDD 進行計算,且只需重新計算該分割槽。
RDD 之間的依賴分為兩種。
Narrow Dependencies (窄依賴):父分割槽對應一個子分割槽。
Shuffle Dependencies (寬依賴):父分割槽對應多個子分割槽。
父分割槽最多被一個子分割槽所用,即一對一或者多對一的關係
對應窄依賴,只需要通過重新計算丟失的那一塊資料來恢復,容錯成本較小。但如果是寬依賴,則當容錯重算分割槽時,因為父分割槽資料只有一部分是需要重運算元分割槽的,其餘資料重算則成了冗餘計算。這時候就需要人為的新增檢查點來提高容錯機制的執行效率。