HDFS
HDFS 是 Hadoop Distributed File System 的簡(jiǎn)稱,顧名思義這是一個(gè)分布式的文件系統(tǒng)。HDFS可以將文件存儲(chǔ)在不同的服務(wù)器上。其組成架構(gòu)如下:

HDFS 主要分為一個(gè)Namenode和多個(gè)Datanode,其作用分別是:
- Namenode: 維護(hù)整個(gè)文件的目錄樹(shù),以及每個(gè)文件對(duì)應(yīng)的數(shù)據(jù)塊列表(在HDFS中每個(gè)文件會(huì)被分塊放在不同的服務(wù)器上)
- Datanode: 文件真實(shí)的存儲(chǔ)位置
寫(xiě)文件流程
在HDFS中,文件會(huì)分成許多個(gè) block(一個(gè)128M,可以通過(guò) hdfs-site.xml 修改), 每一個(gè) block 都會(huì)被復(fù)制多份放在不同的 datanode 上。當(dāng)寫(xiě)入文件的時(shí)候,首先會(huì)向 namenode 發(fā)出寫(xiě)申請(qǐng)。 namenode 會(huì)選擇一些 datanode 來(lái)存放 block。Client會(huì)選擇最近的那一個(gè)datanode進(jìn)行傳輸,其余的會(huì)和這個(gè)datanode形成pipline. 這樣雖然復(fù)制了多份,但是對(duì)于client來(lái)說(shuō)網(wǎng)絡(luò)帶寬并不需要增大。示意圖如下:

這個(gè)過(guò)程是同時(shí)進(jìn)行的。 這過(guò)程完成后,會(huì)接著傳輸?shù)诙€(gè),第三個(gè)block。直到傳輸完成。
讀文件流程
- client訪問(wèn)NameNode,查詢?cè)獢?shù)據(jù)信息,獲得這個(gè)文件的數(shù)據(jù)塊位置列表,返回輸入流對(duì)象。
- 就近挑選一臺(tái)datanode服務(wù)器,請(qǐng)求建立輸入流 。
- DataNode向輸入流中中寫(xiě)數(shù)據(jù),以packet為單位來(lái)校驗(yàn)。
- 關(guān)閉輸入流
寫(xiě)文件出錯(cuò)
在寫(xiě)文件時(shí),一個(gè)block會(huì)被分為許多個(gè)packet。當(dāng)節(jié)點(diǎn)收到某個(gè)packet時(shí),會(huì)將該packet繼續(xù)寫(xiě)往另一個(gè)節(jié)點(diǎn)。并且client會(huì)維持一個(gè) dataqueen 以及一個(gè) ackqueen。當(dāng)所有的節(jié)點(diǎn)收到某個(gè)數(shù)據(jù)包時(shí),才會(huì)將 ackqueen 中的數(shù)據(jù)刪除。當(dāng)其中一個(gè)節(jié)點(diǎn)錯(cuò)誤時(shí),會(huì)將ackqueen中的數(shù)據(jù)重新寫(xiě)入dataqueen。并將正常節(jié)點(diǎn)上當(dāng)前packet指定一個(gè)新的標(biāo)識(shí),以便完成后刪除。例如,最開(kāi)始 dataqueen = [1, 2, 3, 4, 5], 一共3個(gè)節(jié)點(diǎn),當(dāng)寫(xiě)入第3個(gè)包時(shí)節(jié)點(diǎn)2出錯(cuò),此時(shí)dataqueen = [4, 5], ackqueen=[3]. 因此將 ackqueen 放入到 dataqueen 后, dataqueen=[3, 4, 5] 因此能避免丟失任意一個(gè)數(shù)據(jù)包。
任務(wù)執(zhí)行流程
不同的任務(wù)調(diào)度框架下不同。但是基本可以分為以下幾個(gè)部分:
- application 用戶編寫(xiě)的應(yīng)用,這是一個(gè)虛擬的概念。
- driver 用戶寫(xiě)的代碼所在的線程。
- worker 工作節(jié)點(diǎn),負(fù)責(zé)資源的存儲(chǔ)和計(jì)算。
- executor 工作進(jìn)程池,可以并行計(jì)算多個(gè) task
- master 負(fù)責(zé)計(jì)算資源的分配,協(xié)同 driver 與 executor
Standalone模式
Standalone是spark自帶的資源調(diào)度模式,其運(yùn)行模式為:
- 啟動(dòng)應(yīng)用程序,啟動(dòng) SparkContext,這個(gè)過(guò)程中會(huì)啟動(dòng) DAGScheduler 和 Taskcheduler。
- Driver 向 Master 注冊(cè) Application,Master 將該應(yīng)用加入到應(yīng)用隊(duì)列中。并分配Worker。
- 當(dāng) Driver 獲得 Worker 后,會(huì)再 Worker 上創(chuàng)建 Executor,創(chuàng)建完成后將 Executor 注冊(cè)到SparkContext。然后 SparkContext 分配任務(wù)給 Executor 執(zhí)行。
- 任務(wù)執(zhí)行的過(guò)程中不斷的像 Driver 返回執(zhí)行情況,執(zhí)行完畢后 SparkContext 會(huì)回收資源。
Yarn模式
Yarn 是通過(guò) ResourceManager 管理資源,每一個(gè)節(jié)點(diǎn)稱為NodeManager。在 NodeManager 中會(huì)有多個(gè)Container。Executor 會(huì)在 Container 中運(yùn)行。與 Standalone 不同的是,Yarn 通過(guò) ApplicationMaster 來(lái)申請(qǐng)任務(wù)并與 Driver 聯(lián)系。流程如下:
- 向 ResourceManager 申請(qǐng)一個(gè) NodeManager 中的一個(gè) Container 用于執(zhí)行 ApplicationMaster。
- SparkContext 初始化完成后像 ApplicationMaster 通信,注冊(cè)到 ResourceManager 并 申請(qǐng)資源。
- 資源申請(qǐng)成功后,便與 NodeManager 通信申請(qǐng)創(chuàng)建 Container。 SparkContext 再向NodeManager 分配任務(wù)。
- 任務(wù)完成后,SparkContext 向 ResourceManager 申請(qǐng)注銷,并釋放資源。
yarn 有兩種提交模式: client 以及 cluster。client 的 driver 是運(yùn)行在本地的,也就是可以實(shí)時(shí)的觀察計(jì)算的輸出結(jié)果。cluster 的 driver 是運(yùn)行在 NodeManager 上,也就是可以關(guān)閉本地的client后也可以繼續(xù)運(yùn)行,適合不需要交互的場(chǎng)景。
Mesos
Mesos 分為兩種運(yùn)行模型: 粗粒度以及細(xì)粒度模式。 粗粒度模式可以一開(kāi)始就分配好資源,這個(gè)資源在整個(gè) application 的執(zhí)行中是不會(huì)變化的。而細(xì)粒度是隨著任務(wù)的變化,Mesos動(dòng)態(tài)的分配資源。因此在細(xì)粒度的執(zhí)行過(guò)程中,Driver是不直接與 Executor 交互,而是將任務(wù)交給 Mesos Master 進(jìn)行分配,這樣在分配任務(wù)的同時(shí)可以動(dòng)態(tài)的分配資源。
調(diào)優(yōu)
代碼調(diào)優(yōu)
- 重用RDD
- 預(yù)清洗
- 設(shè)置緩存
配置調(diào)優(yōu)
-
--total-executor-cores 100: 調(diào)整可使用的核心數(shù) -
--executor-memory 20G: 調(diào)整 executor 內(nèi)存 -
spark.shuffe.memoryFraction: 調(diào)整 shuffle buffer 大小 - 使用
repartition或coalesce調(diào)整分區(qū)數(shù)
數(shù)據(jù)傾斜調(diào)優(yōu)
- 增加任務(wù)數(shù)量
- 二階段聚合
JOIN 調(diào)優(yōu)
- 如果傾斜的key只占少部分,可以先篩選出這兩個(gè)key,對(duì)大表進(jìn)行隨機(jī)前綴,小表進(jìn)行擴(kuò)容(同樣打上隨機(jī)淺醉)
- 如果傾斜的key占大部分,可以直接不過(guò)濾,然后擴(kuò)容
- 廣播小表
shuffle調(diào)優(yōu)
- 增加 shuffle 內(nèi)存
- 使用預(yù)聚合算子
yarn
調(diào)度的三種模式
- FIFO模式: 任務(wù)先提交則一直獨(dú)占資源,小任務(wù)需要一直等待
- 容量調(diào)度: 容量調(diào)度使用獨(dú)立的專門(mén)隊(duì)列為小隊(duì)列分配資源,但是不能搶占資源
- 公平調(diào)度: 可以公平的分配資源,并且可以搶占資源
存儲(chǔ)模型
spark 存儲(chǔ)同樣采用 master-slave 方式進(jìn)行管理。Master 維護(hù)元數(shù)據(jù),包括 Block 所在位置,所占空間大小。在 spark 中,每一個(gè) partition 都對(duì)應(yīng)一個(gè) block,blockid=rdd_+rddid+_+partitionid