Apache Kyuubi 在小米大資料平臺的應用實踐

語言: CN / TW / HK

導讀:今天分享的主題是《Kyuubi 在小米大資料平臺的應用實踐》,主要分為四部分內容:

  • Kyuubi 在小米的落地過程 

  • 打造易用和高可用的 Kyuubi 服務 

  • 基於 kyuubi 的改進 

  • kyuubi的一些新特性在業務場景的應用

01

Kyuubi 在小米的落地過程

第一個主題:關於Kyuubi在小米的大資料平臺落地過程和實施路徑的分享。

1. 背景介紹

先介紹一下背景,小米的大資料體系在不斷更新和迭代,隨著業務架構、組織架構和技術架構的調整,內部大資料平臺逐漸出現一些狀況:

  • 出現了多個基於SQL的大資料平臺服務,服務於各個業務部門,各自定位又有一定的差異,這樣就給使用者帶來了困擾,到底選擇哪個平臺好,而且我們在使用者支援的過程中發現,同一業務可能需要跨多個數據服務平臺,流程繁瑣。

  • 對於底層表資源的使用存在多套賬號和許可權體系:

a. MySQL/Doris: 系統的自有的 User&Password 認證和許可權體系

b. Hive/Kudu基於 Kerberos 認證和 Sentry 的許可權體系

c. Talos是基於小米內部平臺組織和團隊的認證與授權體系

  • 給使用者使用和管理上帶來了麻煩,沒有統一的資源管理和許可權管理視角,並且底層系統服務賬號會直接暴露給使用者,還會存在安全風險。

2. 構建一站式的大資料開發平臺

上述現象直接導致瞭如下問題:

①對使用者:

  • 多個平臺和多體系給使用者體驗較差,開發資料流程長,不能快速上手。

  • 開發管理效率成本高,資源成本結算和任務管理沒有統一的檢視。

②對平臺:

  • 各自的側重點不同,都不能完全覆蓋大資料場景下的能力需求,同時還有能力重複建設問題,導致資源浪費。

  • 出現問題排查和維護困難,需要堆人力解決。

面對資料平臺難用的情況,提出了構建統一易用的大資料服務平臺整體目標。整體架構能力圍繞資料鏈路解決方案、數倉解決方案、資料服務解決方案來進行建設,提供統一的元資料管理和許可權管理體系。

在這個大背景和動機下,統一的資料入口服務成為了一個非常重要的能力,它主要解決:

  • 使用者的易用性(一致的入口體驗)

  • SQL流量治理(代理多引擎)

  • 資料訪問的安全性管控(入口收斂和降低安全風險)

3. 小米SQL服務歷史發展情況

從上面的背景問題中可以看到,小米內部有幾套大資料處理的SQL服務入口,總體還是圍繞經典的SQL On Hadoop架構體系來構建,逐步從ThriftServer演進到向上抽象一層的SQL Proxy服務,在底層集成了Hive/Spark/Doris等引擎為ETL作業、Ad-Hoc查詢提供支援。

抽離的SparkThriftServer的實現模組作為獨立的SQL Proxy服務,提供:

  • ETL 場景下的HiveServer和Spark APP代理(非常駐)

  • Ad-Hoc 場景下的STS、Kylin、Druid代理

從這裡可以看到SQL Proxy和Kyuubi Server的定位非常相似,但是存在很多不足:

a. SQL Proxy 沒有完全剝離STS的實現,通過反射的方式進行復用,程式碼耦合很高,依賴Spark特定版本,升級困難

b. 底層引擎代理層沒有統一抽象,與其他引擎適配困難,對底層引擎擴充套件性差

c. 無法本地除錯,依賴hadoop配置,在辦公和服務環境網路隔離情況下,必須在開發機上完成完整的功能測試和除錯,開發和部署路徑長

4. 基於Kyuubi 構建統一SQL入口

(1) 為什麼選擇Kyuubi

通過上面的分析,我們發現在業務和架構上都存在著一些問題需要解決。

① 業務上:

  • 在重新打造統一的大資料體系的推動下,構建統一的SQL入口服務勢在必行。

  • 需要更快的分析引擎,這裡我們選擇了Trino。

  • 一套易用、高可用並可以持續演進的服務架構,提升大資料研發的生產力。

SQLProxy架構需要升級:

  • 完全相容HiveThrift協議。

  • 鬆耦合的實現,基於STS實現的完全剝離。

  • 靈活可擴充套件的代理多引擎的適配。

Kyuubi的優勢在於:

  • 與STS和HS2的完全相容一致

  • 高可用和資源隔離

  • 清晰簡潔的架構,可測試、可維護、可擴充套件

  • 社群高質量實現和業界生產環境大量運用

SQLProxy和Kyuubi的架構非常相似,切換成本低。在業務需求和架構升級的雙重推動下,我們選擇了Kyuubi。

(2)架構升級

升級過程和效果與我們的預期一致,可以看到架構相比SQLProxy更加簡潔,擴充套件底層引擎非常容易,而且本地可測試可除錯,極大提升了開發效率。從開發到上線新架構兩週時間就完成了平滑遷移。

升級新架構帶來的效果也非常明顯,相比之前的架構不論程式碼質量、服務穩定性、可維護性和可擴充套件性上都有了重大提升:

  • 多引擎的代理能力(主要支援Spark/Trino/Hive/Doris)。

  • 基於資料平臺workspace的體系在Kyuubi Server端實現了許可權驗證和資源隔離。

  • 更加規範化的Hive Thrift API支援,各種生態視覺化工具(Redash/Datagrip等)完美相容。

(3) 統一SQL服務的現狀

經過半年的遷移推動,每日SQL有效處理量從5W提升到現在的50W規模,已經佔據了整個SQL流量的80%。特別是SparkSQL的流量半年新增到30W。大體流量分佈:Spark 36w/ Trino 12w / Hive 2.5w

各個引擎請求耗時:

  • Spark和Trino持平,平均延時30秒左右,P50在5秒左右

  • Hive的執行效率明顯低於以上兩個引擎,跟Hive的大任務有關,ETL偏多

目前Kyuubi Server 承載真實的SQL流量日均100w左右,可用性仍然可達99.9%以上,非常穩定。

02 

打造易用易維護高可用的Kyuubi服務

1. 構建符合業務需求的Kyuubi

(1) 整體架構

整體架構和流程,主要分為入口服務、認證和許可權適配、底層引擎管理及服務的可觀測性:

  • Kyuubi Server為基礎構建了SQL 統一入口服務 

  • Kyuubi Engine 作為Spark SQL執行引擎層 

  • 獨立Engine Manager服務管理各類計算引擎

  • Kyuubi Server層整合Ranger服務,支援基於資料平臺的統一許可權驗證

  • 擴充套件適配Trino/Hive/Doris引擎服務指標和審計日誌的視覺化

(2) 使用者使用互動

以工作空間(workspace)粒度來保計算資源的隔離的儲存資源(表)安全,與Kyuubi Group 的多租戶類似,我們這裡擴充套件到了其他引擎。

一次完成互動過程:

WorkspaceA下面的使用者使用平臺發放的Token,選擇各類客戶端工具,向引擎提交SQL查詢,Kyuubi Server會自動將使用者SQL提交到該空間所屬的計算引擎上去,來保證使用者使用資源的隔離性。與其他workspace使用者雖是同一入口,但是資源的使用上是隔離的。

Kyuubi Server服務並不具體執行SQL,同一的入口服務不會有太大壓力。

2. 提升使用者側的易用性

(1) 統一認證和表座標的統一

去Kerberos化,採用平臺統一Token方式,解決:

  • Kerberos接入流程繁瑣

  • 普通使用者對kerberos機制難以理解,出現問題排查困難

  • 使用者管理不當,同一賬號下使用者膨脹問題

  • 審計和追蹤不能精確定位到使用者個人

表資源命名的統一規範化,小米內部存在多區域和多類資料來源,如果使用統一的SQL入口服務,需要統一SQL語句的表名規範來避免衝突和統一的管理:

  • 採用Catalog.Schema.Table 三級表名為唯一表名

  • Kyuubi Server端支援JDBC URL預設Catalog/Schema,相容之前SQL中二級或者一級表名

  • 結合URL和SQL Table生成完整的三級表座標,以供使用者許可權認證

(2) Kyuubi Engine 公共資源池

引入Kyuubi Engine公共池主要解決使用者首次進入空間提交SparkSQL的查詢效能問題。上面提到的使用者提交的SQL分析統計,50%的SQL查詢延時都在5秒以下。在沒有提前分配的資源的情況下,使用者提交查詢會冷啟動一個Kyuubi Engine,這是Kyuubi當前的機制。由於小米Yarn提交一個APP的延時在分鐘級別,使用者一個簡單的秒級查詢會延遲到分鐘級別,體感非常差。

因此,藉助Kyuubi Engine Pool的實現,對沒有提前配置和指定資源的workspace使用者,會將SQL路由到已經預先啟動好的Kyuubi Engine Pool,以加快使用者的查詢速度,提升SQL查詢體驗。

3. 升級Spark2.X到Kyuubi Engine

Kyuubi Engine目前只支援Spark3以上,之前我們內部版本都是Spark2,在升級到Kyuubi Engine之前做了相關對比測試,在Kyuubi 架構和SQLProxy架構下,有明顯的效能提升:

  • 在TPC-DS標準測試集上,P50延時有75%的效能提升,長尾基本和SQLProxy效能持平。

  • 在真實的業務場景下,P50延時也有37%的效能提升,長尾也基本跟SQLProxy一致,也就是升級的Kyuubi Engine的效能在多數情況下要優於Spark2,整體上不會比Spark2更差。

4. Kyuubi Server的容器化

在Kyuubi Server的高可用上利用容器化的方式替換了當前Kyuubi Client端通過ZK進行服務發現的高可用模式:

  • 在K8s上部署Kyuubi Server服務,充分利用K8s的彈效能力保障高可用。

  • Kyuubi Server和Kyuubi Engine的部署徹底解耦,作為一個單獨的Thrift RPC代理服務和HTTP服務,去除Hadoop相關的配置環境依賴,和普通業務服務一樣使用LVS做流量負載均衡。

  • 同時藉助內部K8s平臺的CI/CD能力,實現了Kyuubi Server服務的全自動灰度釋出,支援一鍵升級和擴縮容。

5. 基於Workspace的計算資源管理

(1)Engine Manager

由於之前已經實現了對Spark Engine的管理服務,我們將Kyuubi Engine的管理直接從Kyuubi Server剝離,形成了單獨的Engine Manager服務,負責Engine的生命週期管理,配置上下文管理,同時提供服務發現和負載均衡能力。

  • 為管理入口提供引擎配置和生命週期管理。

  • 為Kyuubi Server提供SQL路由的能力。

  • 為運維提供視覺化的監控能力,包括Engine的服務狀態、資源佔用以及繁忙程度等,便於快速運維。

使用者提交的SQL的流程:

  • 首先經過Kyuubi Server入口的認證和許可權驗證。

  • Kyuubi Server向EngineManager可用的Kyuubi Engine地址。

  • EngineManager 向ZK獲取當前使用者空間下可用的Engine,然後統計當前可用Engine的繁忙指標,返回相對空閒的Engine給Kyuubi Server。

  • Kyuubi Server 將SQL提交到EngineManager建議的Engine上去執行。

(2) 使用者提交

圖上是我們的使用者平臺SQL查詢入口,在workspace下的使用者可以非常方便地啟動一個Kyuubi Engine。為降低使用者的門檻,只暴露了資源相關和排隊策略的配置。同時,使用者還可以配置多個Kyuubi Engine例項,來保障當前workspace下的SQL執行的高可用。

(3) Engine的高可用

為什麼需要Kyuubi Engine的高可用?因為在實際環境中,Kyuubi Engine是一直長時間執行的,Spark的SQL執行過程非常複雜,時間一長其穩定性就有了問題:

  • 開啟動態資源策略後丟事件的Bug,導致資源無法釋放。

  • 大任務佔用時間長,可能阻塞一些小任務的執行。

  • Driver端JVM Full GC時間過長和OOM。

  • SQL不合理導致的Engine頻繁重啟。

因此實施了一些高可用的保障策略:

  • workspace級別隔離Engine異常,避免影響其他使用者。

  • 觀測Engine 可用指標,通過繁忙和探活資訊標記是否當前可用。

  • 同一workspace下多個Engine例項(Kyuubi 的Engine Pool機制),提升整體可用性,同時提供基於負載的分發。

  • 發現異常及時自動重啟。

  • 頻繁重啟Engine通過告警機制,人工及時介入。

03

基於Kyuubi的改造

1. Trino和Doris的代理

引入Trino和Doris主要解決OLAP場景的查詢效率問題。

  • Kyuubi 在1.1.0版本還未支援Trino,我們在kyuubi Server端使用Trino-JDBC完成了對Trino引擎的適配。

  • Trino-JDBC實現了流迭代器的模式,每次nextResult都會觸發一次對Trino 引擎的請求。

  • 當前社群Trino-Client實現,會一次性的拉取所有結果集可能導致OOM的風險。

對於Doris的適配也採用了JDBC的方式,由於Doris客戶端本身支援Mysql JDBC,MySQL JDBC的實現方式是全量拉取模式,Kyuubi Server端有OOM的風險。目前通過限制Doris查詢的超時時間來降低大結果集導致OOM的風險。

如果大家後面要擴充套件Kyuubi代理其他JDBC的資料庫支援,一定謹慎處理。

2. SQL HTTP API的支援

關於HTTP API的支援一共實現了V1版本和V2版本,相比社群還是有一些區別。

① V1版本

  • 簡化使用者的互動過程,簡化Hive Thrift RPC的呼叫流程,使用者直接在上層應用程式中通過HTTP 請求就能提交SQL,對一些研發使用者來說是非常友好的。提交SQL根據QueryID,不斷輪詢獲取結果。

  • 複用了Thrift backend Service的實現,水平擴充套件了一層HTTP Fronted Service。底層實現跟Thrift API完全保持一致。

但是也存在一些問題:

  • Kyuubi Service端是有Session狀態的,Step1和Step2必須路由的同一個例項才能獲取到結果,採用IP Hash不能完全解決。

  • 這樣也導致Kyuubi Server HTTP 服務無法水平擴充套件和平滑升級。

②V2版本

為了徹底解決V1的水平擴充套件性問題,在V2版本中將Kyuubi HTTP Server完全無狀態化,通過Kyuubi Engine 直接提供HTTP SQL API。Kyuubi Server只起到出代理的作用。

另外的兩點改進:

  • 徹底解決大結果集的導致Kyuubi Engine OOM的問題,將查詢類的結果直接持久化到HDFS,不經過Spark Driver端。

  • 戶在獲取結果的時候不經過Kyuubi Engine,直接從HDFS層流式獲取結果集。

同時,也不用維持長連結,非常適合ETL的場景。

3. SQL 表列解析

我們在Kyuubi Server端做了許可權認證,需要獲取使用者SQL的真實表名,單獨開發了一個純SQL的解析模組:支援表列血緣關係和SQL型別的提取,支援SparkSQL、Trino兩種語法。

具體解析後的格式如圖,包括型別、輸入輸出表和佇列的列。

後續在具體實際場景中該模組的也應用到了其業務場景,比如表血緣審計日誌,SQL的統計請求分析等安全質量場景,完全複用了我們的SQL表列提取的能力。

04

Kyuubi 新特性的應用 

1. 小檔案合併

解決使用者寫場景可能導致的小檔案過多的問題。使用者一般會提交兩個SQL:一個是業務處理SQL,一個是合併SQL,通過通過workflow方式串聯起來,維護不變。

開啟也非常簡單,可以在Kyuubi Engine啟動階段,SQL提交階段開啟開關。

2. 增量獲取和獲取結果集限制

  • 主要是JDBC下使用者有結果集的查詢導致的OOM問題,開啟增量模式。但有些場景下會有部分分割槽的結果太大,導致取結果過程阻塞,導致有不好的使用者體驗。推薦採用HTTP API 非同步結果獲取方式解決。

  • 對使用者一些預覽資料的SQL,如果訪問的表非常大,限制查詢條數輸出是一個非常好的功能,避免不必要的開銷

3. Z-Ordering

在我們內部畫像場景做相關的測試,Z-Ordering有顯著的提升。

  • 業務查詢時間

  • 儲存空間

  • 查詢掃描資料量

  • 檔案數量

在具體應用中,Z-Ordering的排序規則需要根據實際業務表的資料做相應調整:

  • 我們畫像場景查詢頻次高的列進行排序,效果明顯

  • 超過3個列後的優化並不理想

  • 排序列應選擇基數較大且沒有傾斜的列

Kyuubi Engine Z-Ordering的實現非常巧妙,沒有增加額外的列,直接複用了parquet的原生能力,所以一次生成可以支援多個引擎查詢(只要該引擎支援parequet格式的讀取)。

4. PlanOnly 模式

主要用於非SQL執行的SQL相關場景,比如:

  • 為資料平臺提供語法語義校驗服務

  • SQL 提交前的檢查

  • SQL 語法語義相容性的檢查(Spark2.X->Spark3.X的升級)

PlanOnly模式下SQL不會真正執行,只會輸出解析後的LogicalPlan/SparkPlan。目前為資料平臺單獨提供了語法語義校驗服務,就是採用Kyuubi Engine的PlanOnly模式。

這種應用場景也為我們提供了一種新思路:將Kyuubi Engine作為Yarn APP的服務框架,提供其他場景的服務,比如校驗服務、血緣關係提取服務和SQL的預計算服務等。

5. Scala mode

Scala Code模式完全解放了Kyuubi Engine能力,具備直接通過JDBC提交Scala 程式碼的能力,專門處理一些複雜邏輯的業務。

目前我們的應用場景在運維這塊做了一些嘗試,主要解決我們的運維效率。例如我們要在執行時動態載入使用者自定義的jar包,讀取Thrift格式化的資料。相比之前登入到生產叢集機器打包程式碼執行的流程大大簡化。

05

未來規劃和總結

規劃:

  • 基於業務場景、SQL規則和執行代價事前預測,實現多引擎下的自動路由能力。

  • HTTP API代替Thrift API提交的ETL作業,非同步化取代長連線的方式。

總結:

  • Kyuubi 是非常優秀開源實踐,已經成為小米內部大 資料服務入口的重要基礎架構服務 。

  • 常感謝Kyuubi的社群的貢獻,加速了我們統一 SQL服務的落地 。

  • 信未來Kyuubi會成為大資料場景下的SQL Gateway標杆,與大家一起共建Kyuubi生態 。

今天的分享就到這裡,謝謝大家。

分享嘉賓