閉包引用 概念 所有編程語言都有閉包的概念,閉包就是在一個函數中引用了函數外的變數。 Spark中,普通的變數是在Driver程式中創建的,RDD的計算是在分散式集群中的task程式上進行的。因此,當分散式運算元的函數引用了外部的變數時,Driver會把該變數序列化後通過網路發送給每一個task(只針 ...
閉包引用
概念
所有編程語言都有閉包的概念,閉包就是在一個函數中引用了函數外的變數。
Spark中,普通的變數是在Driver程式中創建的,RDD的計算是在分散式集群中的task程式上進行的。因此,當分散式運算元的函數引用了外部的變數時,Driver會把該變數序列化後通過網路發送給每一個task(只針對普通對象)。
spark中所謂"閉包引用",只是看起來類似各種編程語言中的閉包。而本質上就是對某個對象進行序列化+複製,即Driver把分散式運算元中引用的外部變數序列化後,發送給每個task來使用。
在閉包函數內對外部變數進行修改,閉包外的變數並不會改變。因為在閉包函數內的修改,只是在task上對複製過來的閉包對象副本的修改,並不會影響到driver端的原對象,他們是存在於兩台機器上的獨立的文件,互不影響。
好處
應用於大表join小表的場景,將小表數據(字典表、維度表)發送到大表所在節點的記憶體中,在map階段完成join,無需通過兩個rdd去join,省去了shuffle操作。
適用條件
1、閉包引用的對象,必須實現序列化介面:extends Serializable。
2、被引用的對象,數據量不能太大,否則會導致task端記憶體溢出。
單例對象的閉包引用
單例對象(object對象)只在每個executor進程中持有一份,由其中的多個task線程共用。不要在task中對單例對象進行修改操作,否則會產生線程安全問題。而普通對象在每個task線程中都持有一份,不存線上程安全問題。
廣播變數
閉包引用的場景中,Spark為每個task都複製了一份它需要的數據,當數據量較大且task較多時,必然會給網路io和記憶體資源造成很大壓力,而廣播變數只給每個executor發送一份變數副本,由多個task共用。
和閉包引用的區別
1、閉包引用中,是由driver給每個executor直接發送數據。廣播變數中,是通過bittorrent協議來發送數據的,可以減少通信成本。(所有executor遵循了人人為我,我為人人的原則)。