白話分布式 之 分布式計算框架——Spark

分佈式存儲出現是因為單機存儲資源有限且難以擴展,分佈式計算出現同樣是因為單機計算資源有限且難以擴展。存儲資源一般指磁盤容量,而計算資源通常指內存和 CPU。

我們引用中科院的定義來詳細看一下分佈式計算到底是什麼:

分佈式計算是一種新的計算方式。所謂分佈式計算就是在兩個或多個軟件互相共享信息,這些軟件既可以在同一臺計算機上運行,也可以在通過網絡連接起來的多臺計算機上運行。

分佈式計算比起其它算法具有以下幾個優點:

1、稀有資源可以共享。

2、通過分佈式計算可以在多臺計算機上平衡計算負載。

3、可以把程序放在最適合運行它的計算機上。

這個定義真的是精闢,不僅指出了分佈式計算的內涵,也同樣指出了分佈式計算的問題。我們分解一下這個定義。

首先我們標註一些關鍵詞:軟件,網絡,運行,資源,共享,平衡,負載,適合

我們不看上面的定義,只看這些關鍵詞,便可以勾勒出分佈式計算需要的子系統:

1、調度系統:對應關鍵詞 平衡,適合,負載 --> 想要生活的井井有條,最好有人幫你安排好。

2、通信系統:對應關鍵詞 網絡,共享 --> 想要溝通一起玩耍,至少有個電話吧。

3、計算系統:對應關鍵詞 軟件,資源,運行 --> 想要吃飯,至少有個活廚子吧。

同樣,我們可以先列舉這些關鍵詞的對立面:網絡不可靠,運行出問題,資源不足,共享不暢,分配不平衡,負載過大,不適合 根據這些反向關鍵詞勾勒出分佈式系統可能存在的問題:

1、資源調度不合理,導致負載不平衡,不能充分使用集群資源: 對應關鍵字 資源不足,分配不平衡,負載過大,不適合。

2、計算可靠性不高導致結果錯誤或者計算失敗 : 對應關鍵字 網絡不可靠,運行出問題。

調度問題佔了 4 個關鍵字,佔總關鍵字的 67 %,說明中科院認為調度問題是分佈式計算的最關鍵因素,是的,我們也是這麼認為的。所以我們會首先介紹 spark 的調度系統,然後帶出其他兩個系統,順便將 spark 解決兩個問題的方案帶出來。

Spark 框架

Spark 的調度系統從上到下包括 DAGScheduler(Job 級調度器)和TaskScheduler(Task 級調度器)和 SchedulerBackend(調度資源管理器)組成,其關係如下圖所示:

白話分佈式 之 分佈式計算框架——Spark

為了讓大家快速對這個流程有一個直觀的認識,我們參照例子解釋一下:

學校剛來的校長(DAGScheduler)決定梳理一下學校現狀,統計學校男女學生的人數,出一份報表(Job - 輸出男女人數報表),決定讓秘書先找人按照班級各自統計一下男女人數,每個班產生一個報表,然後讓合併男生和女生的數量(兩個 Stage - 班級報表,報表合併),校長同時規定了最多派多少組人(Executor - 實際執行工作的環境,對應 Java 虛擬機)去幹這件事,每個組最多多少人(Thread - 單個 Executor 中最大的並行工作個體,對應 CPU 核數 - 每個 Thread 只能幹單一的活,要不只統計男生數量,要不只統計女生數量)。

秘書拿到指令後,根據班級的數量,班級人數和班級的位置對組進行具體工作的規劃(比如說哪組人負責那幾個班級最快-離得最近)。

然後秘書到外包公司集團(SchedulerBackend - 專門外包人力的組織)按照規劃要人,外包集團會將人力需求分配到各個公司(Worker),如果正好所有人都被派出了,就告訴秘書等一會兒(Spark 程序啟動時的 Accept 狀態),一旦有人回來了,外包集團就讓這個人按照規劃去對應的幾個班級統計男女人數(Task - 數量等於班級數 * 2 - 因為每個班都要統計男生和女生數量),隨著人員逐漸迴歸,派出的人數也會逐漸跟上規劃。

校長會跟蹤統計的情況,每當有一個班級的男生或者女生被統計出來了,校長就掏出小本在待辦清單上把這個 Task 抹掉,直到所有的都抹掉了,然後去看每個班報表是否都生成了,就認為班級統計(第一個 Stage )完成了,同理,校長也會統計 Stage 數量用來判斷 Job 是否完成了。

雖然這個工作使用 Spark 的框架做有點殺雞用牛刀,但是上面的例子應該會讓大家對於其中的概念有一個大概的認識,我們下面再對這些概念給出相對嚴格的定義。

  1. Job 指一次 action 操作,Spark 對數據的操作包括 transform 操作和 action 操作,action 操作指有數據輸出(無論是輸出到文件還是輸出到控制檯)的操作,spark 是懶的,一段程序只有遇到 action 操作才會真正調度執行。Spark 按照 action 操作對應用進行 Job 切分。
  2. Stage 一個 Job 會根據 Shuffle 被拆分為多個 Stage 。所謂的 shuffle 就是寬依賴。所謂的寬依賴就是父 RDD 的分區影響了多個 RDD 的分區。
白話分佈式 之 分佈式計算框架——Spark

  1. Task Spark 最小執行單元,一般而言數據每個 partition 對應一個 Task。
  2. Driver 就是代碼中的 SparkContext,整個 Spark 作業啟動、調度、監控者。
  3. Worker 可運行的物理節點。
  4. Executor 執行 Spark 的處理程序,也就是一個 JVM進程,如果使用 yarn 調度的話則對應 yarn 中的一個 Container。

這些概念的關係在上面的例子中便可以推演出來,官方的圖則更加簡明一些:

白話分佈式 之 分佈式計算框架——Spark

雖然 Spark 有自己的調度機制和調度邏輯,但是也只能實現多個提交的 Job 內做出優化,如果要針對集群資源情況和負載壓力做出最佳的分配決策,僅憑 Spark 本身是做不到的。所以在工程應用上,很少會單獨部署和使用 Spark ,而是將其與 yarn 結合起來,利用 yarn 資源管理和分配能力給出最優的分配策略。

實際上, MapReduce 和 Storm 也通常會依賴 yarn 的資源管理能力。這也就是上文中第一個問題的答案——不要逞能,專業的事情交給專業的人做。

Spark 的內部通信是非常複雜的,client 與 master 之間, master 與 worker 之間 ,worker 內部之間都有通信,而且整個運作時很快的,資源消耗也是比較大的。所以不會採用阻塞 I/O 的方式在線等待,理所當然的選擇了 NIO(發出響應後立刻返回,釋放資源,等待回調)模型。實際上,幾乎沒有哪個大數據在線系統會不採用這種方案。在 1.6 之前,Spark 採用了基於 Actor 模型的 Akka 通信框架,但是因為一些管理和依賴衝突的考慮,在 1.6 以後替換成了 Netty 框架。

Spark 也使用了一系列的超時機制來防止網絡異常帶來的問題, 通過累加器計數來識別運行時的異常並會使用 Stage 重新提交來解決這些異常。


分享到:


相關文章: