1. 程式人生 > >spark thriftserver程序fullgc導致卡死和計算getsplit時間很長問題

spark thriftserver程序fullgc導致卡死和計算getsplit時間很長問題

背景

餓了麼經驗中談到:“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;

可以跳過快取footer資訊,從而解決driver端記憶體壓力問題。

但要注意這個引數不是對所有SQL有效能提升效果,在極端情況下,如小檔案資料非常多或者單個檔案非常大的情況,使用BI模式可能降低SQL執行效率。

參考: