spark thriftserver程序fullgc導致卡死和計算getsplit時間很長問題
阿新 • • 發佈:2019-01-03
背景
餓了麼經驗中談到:“hive.exec.orc.split.strategy為ETL”,但是這樣可能導致spark thriftserver的記憶體壓力很大,面對大作業會導致full gc從而程序卡死或退出。
原因
先看看split的strategy類別,它有BI,ETL和HYBRID三種,預設是HYBRID
long avgFileSize = totalFileSize / numFiles; switch(context.splitStrategyKind) { case BI: // BI strategy requested through config splitStrategy = new BISplitStrategy(context, fs, dir, children, isOriginal, deltas, covered); break; case ETL: // ETL strategy requested through config splitStrategy = new ETLSplitStrategy(context, fs, dir, children, isOriginal, deltas, covered); break; default: // HYBRID strategy if (avgFileSize > context.maxSize) { splitStrategy = new ETLSplitStrategy(context, fs, dir, children, isOriginal, deltas, covered); } else { splitStrategy = new BISplitStrategy(context, fs, dir, children, isOriginal, deltas, covered); } break; } } else { // no base, only deltas splitStrategy = new ACIDSplitStrategy(dir, context.numBuckets, deltas, covered); }
當avgFileSize大於context.maxSize(最大split大小),會選擇ETL模式,那麼會根據檔案大小來split得到map個數(其目的是保證每個map小於maxSize)
,這樣做的開銷是需要讀orc檔案的footer資訊來根據大小split,對於大作業消耗時間較長。
當avgFileSize小於context.maxSize,會選擇BI模式,則根據每個檔案劃分一個map。這樣省去讀footer資訊過程,可以更快計算出split。
對於spark thriftsever情況,執行大sql會出現fullgc是因為當讀取大作業時driver在getSplit階段從hdfs讀取orc檔案的footer資訊來計算split,對於大作業這個footer資訊會非常大導致driver記憶體滿從而導致full gc,而在計算出split之前full gc不會將快取的footer資訊清除,這也是GC出現後導致長時間卡死原因。調整引數set hive.exec.orc.split.strategy=BI;
但要注意這個引數不是對所有SQL有效能提升效果,在極端情況下,如小檔案資料非常多或者單個檔案非常大的情況,使用BI模式可能降低SQL執行效率。