Spark性能調優之代碼方面的優化


 


Spark性能調優之代碼方面的優化

1.避免創建重復的RDD
    對性能沒有問題,但會造成代碼混亂
 
2.盡可能復用同一個RDD,減少產生RDD的個數
 
3.對多次使用的RDD進行持久化(cache,persist,checkpoint)
如何選擇一種最合適的持久化策略?
     默認MEMORY_ONLY, 性能很高, 而且不需要復制一份數據的副本,遠程傳送到其他節點上(BlockManager中的BlockTransferService),但是這里必須要注意的是,在實際的生產環境中,恐怕能夠直接用這種
策略的場景還是有限的,如果RDD中數據比較多時(比如幾十億),直接用這種持久化
級別,會導致JVM的OOM內存溢出異常。
    如果使用 MEMORY_ONLY級別時發生了內存溢出,建議嘗試使用MEMORY_ONLY_SER級別,該級別會將RDD數據序列化后再保存在內存中,此時每個 partition僅僅是一個字節數組而已,大大減少了對象數量,並降低了內存占用。這種級別 比MEMORY_ONLY多出來的性能開銷,主要就是序列化與反序列化的開銷。
     如果純內存的級別都無法使用,那么建議使用MEMORY_AND_DISK_SER策略,而不是
MEMORY_AND_DISK策略。因為既然到了這一步,就說明RDD的數據量很大,內存無 法完全放下。序列化后的數據比較少,可以節省內存和磁盤的空間開銷。同時該策略會優 先盡量嘗試將數據緩存在內存中,內存緩存不下才會寫入磁盤。
     通常不建議使用DISK_ONLY和后綴為_2的級別因為完全基於磁盤文件進行數據的讀寫 ,會導致性能急劇降低,有時還不如重新計算一次所有RDD。后綴為_2的級別,必須將 所有數據都復制一份副本,並發送到其他節點上,數據復制以及網絡傳輸會導致較大的性 能開銷除非是要求作業的高可用性,否則不建議使用
    
     checkpoint 可以使數據安全,切斷依賴關系(如果某一個rdd丟失了,重新計算的鏈太長?)
 
4.盡量避免使用shuffle類的算子
    廣播變量模擬join(一個RDD比較小,另一個RDD比較大 )
 
5.使用map-side預聚合shuffle操作
    reduceByKey    aggregateByKey
 
6.使用高性能的算子
    有哪些高性能的算子?
         reduceByKey/aggregateByKey 替代 groupByKey
         mapPartitions 替代普通map Transformation算子
         foreachPartitions 替代 foreach Action算子
         repartitionAndSortWithinPartitions  替代repartition與sort類操 作 
         rdd.partitionBy() //其實自定義一個分區器    
         repartition    coalesce(numPartitions,true) 增多分區使用這個
         coalesce(numPartitions,false) 減少分區 沒有shuffle只是合並 partition
 
7.廣播變量
   開發過程中,會遇到需要在算子函數中使用外部變量的場景(尤其是大變量,比如 100M以上的大集合),那么此時就應該使用Spark的廣播(Broadcast)功能來提 升性能,如果使用的外部變量比較大,建議使用Spark的廣播功能,對該變量進行廣播。廣播 后的變量,會保證每個Executor的內存中,只駐留一份變量副本,而Executor中的
task執行時共享該Executor中的那份變量副本。這樣的話,可以 大大減少變量副本 的數量,從而減少網絡傳輸的性能開銷,並減少對Executor內存的占用開銷,降低 GC的頻率
 
    Executor 2G, 2G*0.48
 
8.使用kryo序列化性能?
   • Spark支持使用Kryo序列化機制。Kryo序列化機制, 比默認的Java序列化機制,速度要快
序列化后的數據要更小,大概是Java序列化機制的1/10。所以Kryo序列化優化以后,可
以讓網絡傳輸的數據變少;在集群中耗費的內存資源大大減少
   • 對於這三種出現序列化的地方,我們都可以通過使用Kryo序列化類庫,來優化序列化和 反序列化的性能。 Spark默認使用的是Java的序列化機制,也就是 ObjectOutputStream/ObjectInputStream API來進行序列化和反序列化。但是Spark同 時支持使用Kryo序列化庫,Kryo序列化類庫的性能比Java序列化類庫的性能要高很多。 官方介紹,Kryo序列化機制比Java序列化機制,性能高10倍左右。Spark之所以默認沒有
使用Kryo作為序列化類庫,是因為Kryo要求最好要注冊所有需要進行序列化的自定義類 ,因此對於開發者來說,這種方式比較麻煩
    自定義的類有哪些,都要注冊
 
9.優化數據結構
    盡量 使用字符串代替對象使用原始類型(Int,long)替代字符串使用數組替代集合類型,這樣盡可能地 減少內存占用 ,從而降低GC頻率,提升性能
 
10.使用高性能的fastutil
    • fastutil是擴展了Java標准集合框架(Map、List、Set;HashMap、ArrayList、 HashSet)的類庫,提供了特殊類型的map、set、list和queue;
    • fastutil能夠提供更小的內存占用,更快的存取速度;我們使用fastutil提供的集合類,來 替代自己平時使用的JDK的原生的Map、List、Set,好處在於,fastutil集合類,可以減 小內存的占用,並且在進行集合的遍歷、根據索引(或者key)獲取元素的值和設置元素 的值的時候,提供更快的存取速度;
   •  fastutil最新版本要求Java 7以及以上版本
   •  fastutil的每一種集合類型,都實現了對應的Java中的標准接口(比如fastutil的map,實 現了Java的Map接口),因此可以直接放入已有系統的任何代碼中。
RandomExtractCars
    提供了一些集合,性能更高
    必須是java7以上的版本
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM