極光筆記丨Spark SQL 在極光的建設實踐

極光推送發表於2021-11-09


極光高階工程師——蔡祖光

前言

Spark在2018開始在極光大資料平臺部署使用,歷經多個版本的迭代,逐步成為離線計算的核心引擎。當前在極光大資料平臺每天執行的Spark任務有20000+,執行的Spark SQL平均每天42000條,本文主要介紹極光資料平臺在使用Spark SQL的過程中總結的部分實踐經驗,包括以下方面內容:

Spark Extension的應用實踐
Spark Bucket Table的改造優化
從Hive遷移到Spark SQL的實踐方案

一、Spark Extension應用實踐

Spark Extension作為Spark Catalyst擴充套件點在SPARK-18127中被引入,Spark使用者可以在SQL處理的各個階段擴充套件自定義實現,非常強大高效

1.1 血緣關係解析

在極光我們有自建的後設資料管理平臺,相關後設資料由各資料元件進行資訊收集,其中對Spark SQL的血緣關係解析和收集就是通過自定義的Spark Extension實現的。

Spark Catalyst的SQL處理分成parser,analyzer,optimizer以及planner等多個步驟,其中analyzer,optimizer等步驟內部也分為多個階段,為了獲取最有效的血緣關係資訊,我們選擇最終的planner階段作為切入點,為此我們專門實現了一個planner strategy進行Spark SQL物理執行計劃的解析,並提取出讀寫表等後設資料資訊並儲存到後設資料管理平臺

1.2 許可權校驗

在資料安全方面,極光選擇用Ranger作為許可權管理等元件,但在實際使用的過程中我們發現目前社群版本的Ranger主要提供的還是HDFS、HBase、Hive、Yarn的相關接入外掛,在Spark方面需要自己去實現相關功能,對於以上問題我們同樣選擇用Spark Extension去幫助我們進行許可權方面的二次開發,在實現的過程中我們藉助了Ranger Hive-Plugin的實現原理,對Spark SQL訪問Hive進行了許可權校驗功能的實現。

1.3 引數控制

隨著資料平臺使用Spark SQL的業務同學越來越多,我們發現每個業務同學對於Spark的熟悉程度都有所不同,對Spark配置引數的理解也有好有壞,為了保障叢集整體執行的穩定性,我們對業務同學提交的Spark任務的進行了攔截處理,提取任務設定的配置引數,對其中配置不合理的引數進行遮蔽,並給出風險提示,有效的引導業務同學進行合理的線上操作。

二、Spark Bucket Table的改造優化

在Spark的實踐過程中,我們也積極關注業內其它公司優秀方案,在2020年我們參考位元組跳動對於Spark Bucket Table的優化思路,在此基礎上我們對極光使用的Spark進行了二次改造,完成如下優化項:

Spark Bucket Table和Hive Bucket Table的互相相容
Spark支援Bucket Num是整數倍的Bucket Join
Spark支援Join欄位和Bucket欄位是包含關係的Bucket Join

上述三點的優化,豐富了Bucket Join的使用場景,可以讓更多Join、Aggregate操作避免產生Shuffle,有效的提高了Spark SQL的執行效率.在完成相關優化以後,如何更好的進行業務改造推廣,成為了我們關心的問題。

通過對資料平臺過往SQL執行記錄的分析,我們發現使用者ID和裝置ID的關聯查詢是十分高頻的一項操作,在此基礎上,我們通過之前SQL血緣關係解析收集到的後設資料資訊,對每張表進行Join、Aggregate操作的高頻欄位進行了分析整理,統計出最為合適的Bucket Cloumn,並在這些後設資料的支撐下輔助我們進行Bucket Table的推廣改造。

三、Hive遷移Spark

隨著公司業務的高速發展,在資料平臺上提交的SQL任務持續不斷增長,對任務的執行時間和計算資源的消耗都提出了新的挑戰,出於上述原因,我們提出了Hive任務遷移到Spark SQL的工作目標,由此我們總結出瞭如下問題需求:

如何更好的定位哪些Hive任務可以遷移,哪些不可以
如何讓業務部門無感知的從Hive遷移到Spark SQL
如何進行對比分析,確認任務遷移前後的執行效果

3.1 Hive遷移分析程式的實現

在遷移業務job時,我們需要知道這個部門有哪些人,由於Azkaban在執行具體job時會有執行人資訊,所以我們可以根據執行人來推測有哪些job。分析程式使用了後設資料系統的某些表資料和azkaban相關的一些庫表資訊,用來幫助我們收集遷移的部門下有多少hive job,以及該hive job有多少sql,sql語法通過率是多少,當然在遷移時還需要檢視Azkaban的具體執行耗時等資訊,用於幫助我們在精細化調參的時候大致判斷消耗的資源是多少。

由於線上直接檢測某條sql是否合乎spark語義需要具有相關的讀寫許可權,直接開放許可權給分析程式不安全。所以實現的思路是通過使用後設資料系統儲存的庫表結構資訊,以及azkaban上有采集業務job執行的sql資訊。只要擁有某條sql所需要的全部庫表資訊,我們就能在本地通過重建庫表結構分析該條sql是否合乎spark語義(當然線上環境和本地是有不同的,比如函式問題,但大多情況下是沒有問題的)。

圖3-1-1

以下為某資料部通過分析程式得到的SQL通過率

3.2 SQL執行引擎的無感知切換

目前業務方使用Hive的主要方式是通過beeline去連線hiveserver2,由於livy也提供了thriftserver模組,所以beeline也可以直接連線livy。遷移的策略就是先把合乎Spark語法的SQL發往livy執行,如果執行失敗再切換到Hive進行兜底執行。

beeline可獲取使用者SQL,啟動beeline時通過thrift介面建立livy session,獲取使用者sql傳送給livy 執行,期間執行進度等資訊可以查詢livy獲得,同時一個job對應一個session,以及每啟動一次 beeline對應一個session,當job執行完畢或者beeline被關閉時,關閉livy session。(如果spark不能成功執行則走之前hive的邏輯)


圖3-2-1

有了以上切換思路以後,我們開始著手beeline程式的修改設計

beeline重要類圖如圖3-2-2所示, Beeline類是啟動類,獲取使用者命令列輸入並呼叫Commands類去 執行,Commands負責呼叫JDBC介面去執行和獲取結果, 單向呼叫流程如圖3-2-3所示。


圖3-2-2

圖3-2-3

由圖3-2-2和圖3-2-3可知,所有的操作都是通過DatabaseConnection這個物件去完成的,持有這個 物件的是DatabaseConnections這個物件,所以多計算引擎切換,通過策略適配

DatabaseConnections物件,這樣就能在不修改其他程式碼的情況下切換執行引擎(即獲取不同的 connection)


圖3-2-4

3.3 任務遷移黑名單

前文有說到,當一個Hive任務用SQL分析程式走通,並且在遷移程式用livy進行Spark任務提交以後,還是會有可能執行失敗,這個時候我們會用Hive進行兜底執行保障任務穩定性。但是失敗的SQL會有多種原因,有的SQL確實用Hive執行穩定性更好,如果每次都先用Spark SQL執行失敗以後再用Hive執行會影響任務效率,基於以上目的,我們對遷移程式開發了黑名單功能,用來保障每個SQL可以找到它真正適合的執行引擎,考慮到beeline是輕量級客戶端,識別的功能應該放在livy-server側來做,開發一個類似HBO的功能來將這樣的異常SQL加入黑名單,節省遷移任務執行時間。

目標: 基於HBE(History-Based Executing)的異常SQL識別

有了上述目標以後我們主要通過如下方式進行了SQL黑名單的識別切換

SQL識別限定在相同appName中(縮小識別範圍避免識別錯誤)
得到SQL抽象語法樹的後續遍歷內容後生成md5值作為該sql的唯一性標識
把執行失敗超過N次的SQL資訊寫入黑名單
下次執行時根據賦值規則比較兩條SQL的結構樹特徵
對於在黑名單中的SQL不進行Spark SQL切換

3.4 遷移成果

今年經過遷移程式的遷移改造,HSQL最大降幅為50%+(後隨今年業務增長有所回升)


四、Spark3.0的應用

當前極光使用的Spark預設版本已經從2.X版本升級到了3.X版本,Spark3.X的AQE特性也輔助我們更好的使用Spark

實踐配置優化:

spark3.0.0引數

動態合併shuffle partitions

spark.sql.adaptive.coalescePartitions.enabled true

spark.sql.adaptive.coalescePartitions.minPartitionNum 1

spark.sql.adaptive.coalescePartitions.initialPartitionNum 500

spark.sql.adaptive.advisoryPartitionSizeInBytes 128MB

動態優化資料傾斜,通過實際的資料特性考慮,skewedPartitionFactor我們設定成了1

spark.sql.adaptive.skewJoin.enabled true

spark.sql.adaptive.skewJoin.skewedPartitionFactor 1

spark.sql.adaptive.skewJoin.skewedPartitionThresholdInBytes 512MB

五、後續規劃

目前針對線上執行的Spark任務,我們正在開發一套Spark全鏈路監控平臺,作為我們大資料運維平臺的一部分,該平臺會承擔對線上Spark任務執行狀態的採集監控工作,我們希望可以通過該平臺及時定位發現資源使用浪費、寫入大量小檔案、存在slow task等問題的Spark任務,並以此進行有針對性的優化,讓資料平臺可以更高效的執行。

相關文章