這兩天弄訓(xùn)練數(shù)據(jù)的時(shí)候碰到了一個(gè)大坑
本來數(shù)據(jù)集就比較大巾表,在劃訓(xùn)練樣本的時(shí)候纵寝,訓(xùn)練樣本的分布就出現(xiàn)了不均勻的情況(有的parition多绸狐,有的少)谣妻,主要的癥狀體現(xiàn)在200個(gè)parition的dataframe,前面190個(gè)task都run的飛快芬骄,剩下10個(gè)task猾愿,處理的一個(gè)比一個(gè)慢。點(diǎn)開每個(gè)task的input data size账阻,就會發(fā)現(xiàn)很多parition都是空的匪蟀,或者只有幾KB,在run的task中宰僧,input data一個(gè)大過一個(gè)。
這是典型的數(shù)據(jù)傾斜現(xiàn)象观挎,不及時(shí)處理簡直后患無窮琴儿。
常規(guī)的做法,對dataframe進(jìn)行“撒鹽”處理:就是append上一列column嘁捷,賦值為隨機(jī)數(shù)造成,然后按照這個(gè)隨機(jī)數(shù)做聚合操作,能大大降低數(shù)據(jù)傾斜的發(fā)生雄嚣。
第二是由于數(shù)據(jù)量本來就多晒屎,解決了數(shù)據(jù)傾斜的問題后,在后續(xù)的處理當(dāng)中缓升,頻繁出現(xiàn)了分布式集群中worker節(jié)點(diǎn)失聯(lián)的情況鼓鲁。一般這樣是由于每個(gè)節(jié)點(diǎn)的worker計(jì)算量太大,導(dǎo)致超時(shí)了港谊,或者是因?yàn)楣?jié)點(diǎn)OOM了骇吭,導(dǎo)致節(jié)點(diǎn)掛掉了。
這個(gè)可以看下spark UI歧寺,看看機(jī)器的metric都有沒啥問題燥狰。如果是計(jì)算量太大導(dǎo)致的超時(shí),并不建議修改spark的timeout和heartbeat時(shí)間斜筐,理論上應(yīng)該是有更elegant的方法可以避免超時(shí)的問題龙致。
我后續(xù)的操作應(yīng)該就是每個(gè)worker的計(jì)算量太大了,因?yàn)閒unction要操作的數(shù)據(jù)量都比較大顷链,這樣很容易造成超時(shí)目代,也很容易導(dǎo)致,即使做了shuffle,已然數(shù)據(jù)分配不均像啼。所以這次的教訓(xùn)就是俘闯,盡量讓dataframe的function(udf)每次操作的數(shù)據(jù)量少,這樣才能最大程度利用分布式忽冻。還有就是如果數(shù)據(jù)量大真朗,操作復(fù)雜的話,要及時(shí)觸發(fā)action操作僧诚,不然到后面計(jì)算圖就特別大了遮婶,算起來老慢了。
所以作此總結(jié):
- 及時(shí)觸發(fā)action湖笨,避免后面某次一次性觸發(fā)前面厚重的計(jì)算圖
- 根據(jù)機(jī)器旗扑,及時(shí)提高計(jì)算并行度(通過設(shè)置spark的參數(shù),或者通過repartition增加df parition的數(shù)量慈省,和core總數(shù)相同)
- 手動shuffle(撒鹽
- udf應(yīng)該盡可能處理少量的數(shù)據(jù)臀防,和簡單的邏輯