Spark性能調優:廣播大變量broadcast
原文鏈接:https://blog.csdn.net/leen0304/article/details/78720838
概要
有時在開發過程中,會遇到需要在算子函數中使用外部變量的場景(尤其是大變量,比如100M以上的大集合),那么此時就應該使用Spark的廣播(Broadcast)功能來提升性能。
在算子函數中使用到外部變量時,默認情況下,Spark會將該變量復制多個副本,通過網絡傳輸到task中,此時每個task都有一個變量副本。如果變量本身比較大的話(比如100M,甚至1G),那么大量的變量副本在網絡中傳輸的性能開銷,以及在各個節點的Executor中占用過多內存導致的頻繁GC,都會極大地影響性能。
因此對於上述情況,如果使用的外部變量比較大,建議使用Spark的廣播功能,對該變量進行廣播。廣播后的變量,會保證每個Executor的內存中,只駐留一份變量副本,而Executor中的task執行時共享該Executor中的那份變量副本。這樣的話,可以大大減少變量副本的數量,從而減少網絡傳輸的性能開銷,並減少對Executor內存的占用開銷,降低GC的頻率。
問題分析
Spark Application的Driver進程,其實就是我們寫的Spark作業打成的jar運行起來的進程,以隨機抽取map步驟為例,其工作時過程大致為:
這種默認的情況下,task執行的算子中使用了外部的變量,每個task都會獲取一份變量的副本,有什么缺點呢?在什么情況下會出現性能上的惡劣的影響呢?
因為map本身是不小,存放數據的一個單位是Entry,還有可能會用鏈表的格式的來存放Entry鏈條,所以map是比較消耗內存的數據格式。比如,map總共是1M。你前面調優都調的特好,資源給的到位,配合着資源並行度調節的絕對到位,設置1000個task,大量task的確都在並行運行。
第一點,這些task里面都用到了占用1M內存的map,那么首先,map會拷貝1000份副本,通過網絡傳輸到各個task中去,給task使用。總計有1G的數據,會通過網絡傳輸。網絡傳輸的開銷不容樂觀啊!網絡傳輸也許就會消耗掉你的spark作業運行的總時間的一小部分。
第二點,map副本傳輸到了各個task上之后是要占用內存的。也許1個map的確不大,也就1M,但1000個map分布在你的集群中,一下子就耗費掉1G的內存。這對性能會有什么影響呢?
首先不必要的內存的消耗和占用,就導致了你在進行RDD持久化到內存,也許就沒法完全在內存中放下,就只能寫入磁盤,最后導致后續的操作在磁盤IO上消耗性能;還有可能你的task在創建對象的時候,也許會發現堆內存放不下所有對象,也許就會導致頻繁的垃圾回收器的回收(GC)。GC的時候一定是會導致工作線程停止,也就是導致Spark暫停工作那么一點時間。頻繁GC的話對Spark作業的運行的速度會有相當可觀的影響。
這種舉例的隨機抽取的map為1M還算小的,如果你是從哪個表里面讀取了一些維度數據,比方說,所有商品品類的信息,在某個算子函數中要使用到,也許會達到100M,如果有1000個task,就會有100G的數據進行網絡傳輸,集群瞬間因為這個原因消耗掉100G的內存。
廣播大變量
如上圖所示,每個Executor會對應自己的BlockManager,BlockManager是負責管理某個Executor對應的內存和磁盤上的數據。
廣播變量初始的時候就在Drvier上有一份副本,task在運行的時候,想要使用廣播變量中的數據,此時首先會在自己本地的Executor對應的BlockManager中,嘗試獲取變量副本。如果本地沒有,那么就從Driver遠程拉取變量副本,並保存在本地的BlockManager中,此后這個executor上的task都會直接使用本地的BlockManager中的副本。executor的BlockManager除了從driver上拉取,也可能從其他節點的BlockManager上拉取變量副本,距離越近越好。
廣播變量的優點:不是每個task一份變量副本,而是變成每個節點的executor才一份副本。這樣的話,就可以讓變量產生的副本大大減少。
根據在實際企業中的生產環境舉例來說:總共有50個executor,1000個task,一個map大小為10M。
默認情況下,1000個task,1000份副本,共有10G的數據進行網絡傳輸,在集群中,耗費10G的內存資源。
如果使用了廣播變量,50個execurtor就只有50個副本,有500M的數據進行網絡傳輸,而且不一定都是從Driver傳輸到每個節點,還可能是就近從最近的節點的executor的bockmanager上拉取變量副本,網絡傳輸速度大大增加,只有500M的內存消耗。
之前是10000M,現在是500M,大約20倍以上的網絡傳輸性能消耗的降低,20倍的內存消耗的減少。對性能的提升和影響,還是很客觀的。
雖然說,不一定會對性能產生決定性的作用。比如運行30分鍾的spark作業,可能做了廣播變量以后,速度快了2分鍾,或者5分鍾。但是一點一滴的調優,積少成多,最后還是會有效果的。