Spark在攜程的實踐(一)

一、Spark在攜程應用的現狀

集群規模:

平均每天MR任務數:30W+

開發平臺:

調度系統運行的任務數:10W+
每天運行任務實例數:23W+
ETL/計算任務:~58%

查詢平臺:

adhoc查詢:2W+
支持Spark/Hive/Presto

Spark在攜程的實踐(一)

二、Hive與Spark的區別

Hive:

優點:運行穩定,客戶端內存消耗小。
存在問題:生成多個MapReduce作業;中間結果落地,IO開銷大;頻繁申請和釋放container,資源沒有合理充分利用

Spark:

快:高效的DAG執行引擎,可以基於內存來高效的處理數據流,節省大量IO開銷
通用性:SparkSQL能直接使用HiveQL語法,Hive Metastore,Serdes,UDFs

Spark在攜程的實踐(一)

三、遷移SparkSQL的挑戰

兼容性:

Hive原先的權限控制
SQL語法,UDF和Hive的兼容性

穩定性:

遷移透明,低優先級用戶無感知
監控作業遷移後成功率及運行時長對比

準確性:

數據一致

功能增強:

用戶體驗,是否易用,報錯信息是否可讀
潛在Bug
周邊系統配合改造
血緣收集

四、兼容性改造

移植hive權限

Spark沒有權限認證模塊,可對任意表進行查詢,有安全隱患
需要與Hive共享同一套權限

方案:

執行SQL時,對SQL解析得到LogicalPlan,對LogicalPlan進行遍歷,提取讀取的表及寫入的表,調用Hvie的認證方法進行檢查,如果有權限則繼續執行,否則拒絕該用戶的操作。
SQL語法和hive兼容
Spark創建的某些視圖,在Hive查詢時報錯,Spark創建的視圖不會對SQL進行展開,視圖定義沒有當前的DB信息,Hive不兼容讀取這樣的視圖

方案:

保持與Hive一致,在Spark創建和修改視圖時,使用hive cli driver去執行create/alter view sql
UDF與hive兼容
UDF計算結果不一樣,即使是正常數據,Spark返回null,Hive結果正確;異常數據,Spark拋exception導致作業失敗,Hive返回的null。

方案:

Spark函數修復,比如round函數


將hive一些函數移植,並註冊成永久函數
整理Spark和Hive語法和UDF差異
五、穩定性和準確性

穩定性:

遷移透明:調度系統對低優先級作業,按作業粒度切換成Spark執行,失敗後再切換成hive
灰度變更,多種變更規則:支持多版本Spark,自動切換引擎,Spark v2 -> Spark v1 -> Hive;灰度推送參數,調優參數,某些功能
監控:每日統計spark和hive運行對比,每時收集作業粒度失敗的Spark作業,分析失敗原因
準確性:
數據質量系統:校驗任務,檢查數據準確性

六、功能增強

Spark Thrift Server:

1、基於delegation token的impersontion

Driver:為不同的用戶拿delegation token,寫到staging目錄,記錄User->SQL->Job映射關係,分發task帶上對應的username

Executor

:根據task信息帶的username找到staging目錄下的token,加到當前proxy user的ugi,實現impersonate

2、基於zookeeper的服務發現,支持多臺server

這一塊主要移植了Hive zookeeper的實現

3、限制大查詢作業,防止driver OOM

限制每個job產生的task最大數量
限制查詢SQL的最大行數,客戶端查詢大批量數據,數據擠壓在Thrift Server,堆內內存飆升,強制在只有查的SQL加上limit
限制查詢SQL的結果集數據大小

4、監控

對每個server定時查詢,檢測是否可用
多運行時長較久的作業,主動kill

用戶體驗

用戶看到的是類似Hive MR進度的日誌,INFO級別日誌收集到ES,可供日誌的分析和排查問題

收集生成的表或者分區的numRows numFile totalSize,輸出到日誌

對簡單的語句,如DDL語句,自動使用–master=local方式啟動

Combine input Format

在HadoopTableReader#makeRDDForTable,拿到對應table的InputFormatClass,轉換成對應格式的CombineInputFormat
通過開關來決定是否啟用這個特性
set spark.sql.combine.input.splits.enable=true
通過參數來調整每個split的total input size
mapreduce.input.fileinputformat.split.maxsize=256MB 10241024
之前driver讀大表高峰時段split需要30分鐘不止,才把任務提交上,現在只要幾分鐘就算好split的數量並提交任務,也解決了一些表不大,小文件多,能合併到同一個task進行讀取


分享到:


相關文章: