Spark知識點整理

Spark知識點整理

版本:Spark-2.1.1

Spark架構

Spark架構主要包含如下角色:

  • Driver: 主計算進程,Spark job的驅動器
  • Executor: 執行器,Worker上的計算進程
  • Cluster Master: 主節點,在standalone模式中爲主節點,控制整個集羣,監控Worker. 在Yarn模式中充當資源管理器(Resource Manager)
  • Worker: 從節點,負責控制計算節點,啓動Executor或Driver

Driver

Spark的驅動器是執行main方法的進程,負責創建SparkContext,創建RDD,以及進行RDD的轉化操作和行動操作的執行。Driver具有以下職能:

  1. 把用戶程序轉爲Job
  2. 跟蹤Executor運行狀況
  3. 爲執行器節點調度任務
  4. UI展示應用運行狀況

Executor

Spark Executor是一個工作進程,負責在Spark作業中運行任務,任務間相互獨立,Spark應用啓動時,Executor節點同時啓動,並且始終伴隨着整個Spark應用的生命週期而存在。如果有Executor節點發生了故障或崩潰,Spark應用也可以繼續執行,會將出錯節點上的任務調度到其他Executor上繼續執行。Executor具有以下職能:

  1. 負責運行Spark Task, 並將結果返回給Driver進程
  2. 通過自身的塊管理器(Block Manager)爲用戶程序中要求緩存的RDD提供內存式存儲. RDD是直接存儲在Executor進程內的,因此任務可以在運行時充分利用緩存加速運算

Driver與Executor關係

  • Executor: 接收任務並執行任務。RDD算子中的計算功能由Executor執行
  • Driver: 創建Spark Context對象的應用程序。Spark程序除了計算RDD計算以外的邏輯由Driver執行,Executor代碼中引用的Driver部分的對象必須是可序列化的,因爲可能需要網絡傳輸

Spark運行流程

在這裏插入圖片描述

運行模式

Local模式

本地模式,Master和Worker均爲本機,可以斷點調試

Standalone模式

使用Spark本身的資源管理和調度

在這裏插入圖片描述

Yarn模式

使用Yarn作爲Spark的資源管理和調度器,又分爲Yarn-client模式和Yarn-cluster模式兩種,涉及ResourceManager/NodeManager/ApplicationMaster/Container等組件

Yarn-client模式

  • driver運行在client客戶端
  • client與Executor Container通信進行作業調度
  • 適用於調試,在客戶端可以看到日誌
  • client與Yarn集羣的連接斷開或client關閉,任務就掛了

Yarn-cluster模式

  • driver運行在ApplicationMaster中
  • ApplicationManager與Executor Container通信進行作業調度
  • 日誌需要登錄到Yarn集羣的節點才能看到
  • client關閉或斷開,任務不受影響,繼續運行
  • 適用於生產環境

ResourceManager

  • 處理客戶端請求
  • 監控NodeManager
  • 啓動或監控ApplicationMaster
  • 資源的分配與調度

NodeManager

  • 管理單個節點上的資源
  • 處理來自ResourceManager的命令
  • 處理來自ApplicationMaster的命令

ApplicationMaster

  • 負責數據切分
  • 爲應用程序申請資源並分配給內部的任務
  • 任務的監控與容錯

Container

Yarn的資源抽象,封裝了某個節點上的多維度資源,如內存、CPU、磁盤、網絡

工作流程

在這裏插入圖片描述

RDD

什麼是RDD

RDD (Resilient Distributed Dataset,分佈式彈性數據集),是Spark的基本數據結構,在代碼中是一個抽象類,代表不可變、可分區、裏面的元素可並行計算的集合。RDD源碼的設計模式類似Java IO,使用了裝飾器模式,是對各種數據操作的封裝。

RDD的屬性

  • 一組分區(partition),即數據集的基本組成單位
  protected def getPartitions: Array[Partition]
  • 一個計算每個分區的函數
  def compute(split: Partition, context: TaskContext): Iterator[T]
  • RDD之間的依賴關係,也叫『血緣』
  protected def getDependencies: Seq[Dependency[_]] = deps
  • Partioner,RDD的分區函數
  @transient val partitioner: Option[Partitioner] = None
  • 一個列表,存儲每個Partition的優先位置(preferred location)
  protected def getPreferredLocations(split: Partition): Seq[String] = Nil
  • 理念:移動數據不如移動計算

RDD的特點

  • 分區

    • Spark的數據是分區的,分區使得並行計算成爲可能
    • 只有K-V數據纔有分區器
    • Spark支持Hash分區器和Range分區器
  • 只讀

    • RDD不能修改,只能通過已有的RDD經過算子變換成新的RDD
    • 兩類算子
      • Transformations: 構建RDD的血緣,不立即執行計算
      • Actions: 觸發RDD計算,將結果寫入外部系統
  • 依賴

    • 窄依賴:上下游RDD之間的依賴是一一對應的
    • 寬依賴:一個下游RDD依賴多個上游RDD
    • 通過依賴關係可以將一個Spark任務描述爲一個DAG(有向無環圖)
    • 寬依賴是劃分stage的依據
    • 通過rdd.dependencies查看依賴的類型(OneToOneDependencySuffleDependency
    • 通過rdd.toDebugString查看依賴血緣
  • 緩存

    • 可以將RDD緩存到內存,只有第一次根據RDD的血緣計算,之後的計算直接從內存中取緩存
    • 使用RDD的persistcache方法進行緩存,persist默認會把數據以序列化的形式存儲在JVM的堆空間中
  • 持久化

    • 對長時間的任務,將中間RDD持久化到checkpoint,加速容錯恢復
    • 在SparkContext中設置檢查點保存目錄(sc.setCheckpointDir(dir),通常dir設置爲HDFS路徑),然後調用RDD的checkpoint方法
    • checkpoint會打斷血緣,checkpoint後的RDD的血緣會從checkpoint開始

創建RDD

從內存中創建RDD

  • parallelize

  • makeRDD,底層實現使用parallelize

從外部存儲創建RDD

  • textFile

Spark任務劃分

  • Application: 初始化一個SparkContext即生成一個Application

  • Job: 一個Action算子即生成一個Job

  • Stage: 根據RDD之間的依賴關係將Job劃分成不同的Stage, 遇到一個寬依賴則劃分一個新的Stage

  • Task: 將Stage最後一個RDD的分區分發到不同的Executor,每個Executor上執行一個Task

廣播變量和累加器

  • RDD: 分佈式數據集
  • 廣播變量: 分佈式只讀變量(需要註冊)
    • 使用廣播變量可以減少網絡傳輸和內存使用:從每個task存儲一份變量到每個Executor存儲一份變量
  • 累加器: 分佈式只寫變量(多個task共同操作同一個變量)

SparkSQL

DataFrame

  • since Spark 1.3

  • 類似傳統數據庫的二維表

  • SparkSession是創建DataFrame和執行SQL的入口

DataSet

  • since Spark 1.6

  • DataFrame的一個擴展,類似Hibernate對數據表的封裝

Spark Streaming

  • Spark Streaming 架構

在這裏插入圖片描述

  • Spark Streaming編程的核心對象是DStream,是對一個時間片(時間片長度可以設置)的數據的封裝. DStream的常用方法與RDD類似

  • 有狀態轉化操作:保存了過去的時間片的狀態, 例如updateStateByKey, mapWithStates

Spark shuffle

Spark的shuffle發生在寬依賴算子,是劃分兩個stage的依據。在Spark 1.6之前,Spark的shuffle主要採用HashShuffleWriter;從Spark 1.6之後,Spark的shuffle主要採用SortShuffleWriter,但是當輸出分區數較少時會採用BypassMergeSortShuffleWriter.

HashShuffleWriter

基於Hash的shuffle在每個map task/executor會爲每一個輸出分區形成一個文件,然後reduce task去取對應的文件。這樣做的缺點是shuffle過程中產生很多小文件讀寫,並且這些小文件還要進行網絡傳輸,效率低,容易OOM,因此在Spark 1.6中放棄了基於Hash的shuffle作爲主要shuffle方式的設計思路。

SortShuffleWriter

Spark 1.6之後主要的shuffle方式,非常類似Hadoop Mapreduce的shuffle. map task的計算結果寫入一個內存數據結構(可以類比Mapreduce的環形緩衝區),內存數據結構滿了就會發生溢寫,map task執行完後把溢寫的多個小文件合用MergeSort歸併成一個index file和一個data file,reduce task根據index file去fetch自己對應的data.

BypassMergeSortShuffleWriter

在Spark 1.6之後,當不存在map side combine(即aggregator)且輸出分區數量小於spark.shuffle.sort.bypassMergeThreshold指定的閾值(默認爲200)時,使用BypassMergeSortShuffleWriter替代SortShuffleWriter. BypassMergeSortShuffleWriter的思路類似HashShuffleWriter,但是每個map task爲所有reduce task創建各自的輸出文件後,在map task執行完後會將各個reduce task對應的文件合併成一個文件,並建立索引文件。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章