Spark性能優化—基礎篇

內容學習自美團技術團隊和馬中華老師,向前輩致敬。

1 Spark開發中性能優化的基本原則

  • 避免創建重複的RDD
val rdd1 = sc.textFile("hdfs://192.168.0.1:9000/hello.txt")
rdd1.map(...)
val rdd2 = sc.textFile("hdfs://192.168.0.1:9000/hello.txt")
rdd2.reduce(...)
  • 儘可能複用同一個RDD
    比如說,有一個RDD的數據格式是key-value類型的,另一個是單value類型的,這兩個RDD的value數據是完全一樣的。那麼此時我們可以只使用key-value類型的那個RDD,因爲其中已經包含了另一個的數據。對於類似這種多個RDD的數據有重疊或者包含的情況,我們應該儘量複用一個RDD,這樣可以儘可能地減少RDD的數量,從而儘可能減少算子執行的次數。
  • 對多次使用的RDD進行持久化
    rdd.cache()
  • 儘量避免使用shuffle類算子
    shuffle過程,簡單來說,就是將分佈在集羣中多個節點上的同一個key,拉取到同一個節點上,進行聚合或join等操作。
    shuffle過程中,各個節點上的相同key都會先寫入本地磁盤文件中,然後其他節點需要通過網絡傳輸拉取各個節點上的磁盤文件中的相同key。而且相同key都拉取到同一個節點進行聚合操作時,還有可能會因爲一個節點上處理的key過多,導致內存不夠存放,進而溢寫到磁盤文件中。因此在shuffle過程中,可能會發生大量的磁盤文件讀寫的IO操作,以及數據的網絡傳輸操作。磁盤IO網絡數據傳輸也是shuffle性能較差的主要原因。
    因此在我們的開發過程中,能避免則儘可能避免使用xxxByKey(reduceByKey、sortByKey、groupByKey等)、join、distinct、repartition等會進行shuffle的算子,儘量使用map類的非shuffle算子。這樣的話,沒有shuffle操作或者僅有較少shuffle操作的Spark作業,可以大大減少性能開銷。
  • 使用map-side預聚合的shuffle操作
    shuffle類算子的三個缺點:磁盤IO、網絡數據傳輸、數據傾斜。
    所謂的map-side預聚合,說的是在每個節點本地對相同的key進行一次聚合操作,類似於MapReduce中的本地combiner。map-side預聚合之後,每個節點本地就只會有一條相同的key,因爲多條相同的key都被聚合起來了。其他節點在拉取所有節點上的相同key時,就會大大減少需要拉取的數據數量,從而也就減少了磁盤IO以及網絡傳輸開銷。
    通常來說,在可能的情況下,建議使用reduceByKey或者aggregateByKey算子來替代掉groupByKey算子。因爲reduceByKey和aggregateByKey算子都會使用用戶自定義的函數對每個節點本地的相同key進行預聚合。而groupByKey算子是不會進行預聚合的,全量的數據會在集羣的各個節點之間分發和傳輸,性能相對來說比較差。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章