天天看點

看SparkSql如何支撐企業數倉

企業級數倉架構設計與選型的時候需要從開發的便利性、生态、解耦程度、性能、 安全這幾個緯度思考。本文作者:驚帆 來自于資料平台 EMR 團隊

前言

Apache Hive 經過多年的發展,目前基本已經成了業界建構超大規模資料倉庫的事實标準和資料處理工具,Hive 已經不單單是一個技術元件,而是一種設計理念。Hive 有 JDBC 用戶端,支援标準 JDBC 接口通路的 HiveServer2 伺服器,管理中繼資料服務的 Hive Metastore,以及任務以 MapReduce 分布式任務運作在 YARN 上。

标準的 JDBC 接口,标準的 SQL 伺服器,分布式任務執行,以及中繼資料中心,這一系列組合讓 Hive 完整的具備了建構一個企業級資料倉庫的所有特性,并且 Hive 的 SQL 伺服器是目前使用最廣泛的标準伺服器。

雖然 Hive 有非常明顯的優點,可以找出完全替代 Hive 的元件寥寥無幾,但是并不等于 Hive 在目前階段是一個完全滿足企業業務要求的元件,很多時候選擇 Hive 出發點并不是因為 Hive 很好的支援了企業需求,單單是因為暫時找不到一個能支撐企業訴求的替代服務。

企業級數倉建構需求

數倉架構通常是一個企業資料分析的起點,在數倉之下會再有一層資料湖,用來做異構資料的存儲以及資料的冷備份。但是也有很多企業,特别是幾乎完全以結構化資料為主的企業在實施上會把資料湖和企業數倉庫合并,基于某個數倉平台合二為一。

企業在考慮建構自身數倉體系的時候,雖然需要參考現有的行業技術體系,以及可以選擇的元件服務,但是不能太過于局限于元件本身,尋找 100%開箱即用的産品。太過于局限于尋找完全契合的元件服務必然受限于服務本身的實作,給未來擴充留下巨大的限制。企業資料倉庫架構必然不等于一個元件,大部分企業在數倉架構實施的都是都是基于現有的部分方案,進行基于自己業務合适的方向進行部分開發與定制,進而達到一個半自研的穩态,既能跟上業務變化的速度,又不過于依賴和受限于元件自身的發展。

一般來說企業級數倉架構設計與選型的時候需要從以下幾個緯度思考:

  • 開發的便利性:所選擇的數倉架構是否具有很好的開發生态,可以提供不同類型的開發态接口,不限于 SQL 編輯器,代碼送出,以及第三方工具整合。
  • 生态:所選擇實作引擎自身是否有很好的生态功能,或者是否可以很好的與其他服務內建,例如資料湖引擎 delta lake,icebeg,hudi 等優秀元件出現,但是 Hive 內建的節奏卻非常慢。
  • 解耦程度:分布式任務必然需要多個元件的協調,例如分布式存儲,資源管理,排程等,像 Hive 就重度依賴于 YARN 體系,計算引擎也與 MR 強綁定,在解耦方面較弱,如果企業考慮在 K8S 上建構自己的計算引擎,Hive 面臨的局限會更加明顯。
  • 性能:整體架構是否擁有更好的性能。
  • 安全:是否支援不同級别,不同力度的使用者通路和資料安全鑒權體系。

對于企業數倉架構來說,最重要的是如何基于企業業務流程來設計架構,而不是基于某個元件來擴充架構。

看SparkSql如何支撐企業數倉

一個企業數倉的整體邏輯如上圖所示,數倉在建構的時候通常需要 ETL 處理和分層設計,基于業務系統采集的結構化和非結構化資料進行各種 ETL 處理成為 DWD 層,再基于 DWD 層設計上層的資料模型層,形成 DM,中間會有 DWB/DWS 作為部分中間過程資料。

從技術選型來說,從資料源的 ETL 到資料模型的建構通常需要長時任務,也就是整個任務的運作時間通常是小時及以上級别。而 DM 層主要是支援業務的需求,對實效性要求比較高,通常運作在 DM 層上的任務時間在分鐘作為機關。

基于如上的分層設計的架構圖可以發現,雖然目前有非常多的元件,像 Presto,Doris,ClickHouse,Hive 等等,但是這些元件各自工作在不同的場景下,像數倉建構和互動式分析就是兩個典型的場景。

互動式分析強調的是時效性,一個查詢可以快速出結果,像 Presto,Doris,ClickHouse 雖然也可以處理海量資料,甚至達到 PB 及以上,但是主要還是是用在互動式分析上,也就是基于資料倉庫的 DM 層,給使用者提供基于業務的互動式分析查詢,友善使用者快速進行探索。由于這類引擎更聚焦在互動式分析上,是以對于長時任務的支援度并不友好,為了達到快速擷取計算結果,這類引擎重度依賴記憶體資源,需要給這類服務配置很高的硬體資源,這類元件通常有着如下限制:

  • 沒有任務級的重試,失敗了隻能重跑 Query,代價較高。
  • 一般全記憶體計算,無 shuffle 或 shuffle 不落盤,無法執行海量資料。
  • 架構為了查詢速度快,執行前已經排程好了 task 執行的節點,節點故障無法重新排程。

一旦發生任務異常,例如網絡抖動引起的任務失敗,機器當機引起的節點丢失,再次重試所消耗的時間幾乎等于全新重新送出一個任務,在分布式任務的背景下,任務運作的時間越長,出現錯誤的機率越高,對于此類元件的使用業界最佳實踐的建議也是不超過 30 分鐘左右的查詢使用這類引擎是比較合适的。

而在離線數倉場景下,幾乎所有任務都是長時任務,也就是任務運作時常在小時及以上,這時就要求執行 ETL 和建構數倉模型的元件服務需要具有較高的容錯性和穩定性,當任務發生錯誤的時候可以以低成本的方式快速恢複,盡可能避免因為部分節點狀态異常導緻整個任務完全失敗。

可以發現在這樣的訴求下類似于 Presto,Doris,ClickHouse 就很難滿足這樣的要求,而像 Hive,Spark 這類計算引擎依托于 Yarn 做資源管理,對于分布式任務的重試,排程,切換有着非常可靠的保證。Hive,Spark 等元件自身基于可重算的資料落盤機制,確定某個節點出現故障或者部分任務失敗後可以快速進行恢複。資料儲存于 HDFS 等分布式存儲系統上,自身不管理資料,具有極高的穩定性和容錯處理機制。

反過來,因為 Hive,Spark 更善于處理這類批處理的長時任務,是以這類元件不擅長與上層的互動式分析,對于這種對于時效性要求更高的場景,都不能很好的滿足。是以在考慮建構數倉的時候,通常會選擇 Hive,Spark 等元件來負責,而在上層提供互動式分析查詢的時候,通常會使用 Presto,Doris,ClickHouse 等元件。

歸納下來如下:

  • Presto,Doris,ClickHouse:更注重互動式分析,對單機資源配置要求很高,重度依賴記憶體,缺乏容錯恢複,任務重試等機制,适合于 30 分鐘以内的任務,通常工作在企業的 DM 層直接面向業務,處理業務需求。
  • Hive,Spark:更注重任務的穩定性,對網絡,IO 要求比較高,有着完善的中間臨時檔案落盤,節點任務失敗的重試恢複,更加合适小時及以上的長時任務運作,工作在企業的的 ETL 和資料模型建構層,負責清洗和加工上層業務所需要的資料,用來支撐整個企業的數倉建構。

一個企業在實施資料平台的時候,由多個不同元件各自工作在不同的架構層中,無法互相取代,互相協作配合,承載整個企業的資料平台業務。

企業級數倉技術選擇

Google 發表的三篇論文從存儲,計算,檢索三個方向闡述了海量資料下一種新的分布式資料加工處理技術,這三個方向被雅虎 Nutch 團隊實作後貢獻給 Apache,也就是目前大家看到的 HDFS,MapReduce 和 HBase,形成了早期 Hadoop 的三大利器。

然而這三大利器更聚焦在異構資料的資訊提取處理上,沒有提供對結構化資料很友好的類似 SQL 文法的分析入口,同時在程式設計态的支撐也不夠友好,隻有 Map 和 Reduce 兩階段,嚴重限制了業務處理的實作,雅虎團隊也是爬蟲相關業務孵化而出,可以看出 Hadoop 早期的三大套件有着如下特點:

  • 門檻高,需要程式設計實作,并且程式設計态受限于 MapReduce 的兩階段限制。
  • 以離散資料處理為主,對分析能力,查詢等常用資料分析功能支援不足。
  • 沒有互動式用戶端,無法實作互動式探索。

Hive 就是誕生在這樣的較大的行業背景下,Hive 的出現剛好彌補了 Hadoop 隻能用來做離線資料處理這個缺陷,提供了一種常用的分析接口,并且提供了非常好的使用者互動方式。

看SparkSql如何支撐企業數倉

Hive 整體架構如上圖所示(本圖來自于 Hive 官網),Hive 提供 JDBC 接口實作支援以程式設計形式進行互動,同時業内幾乎所有 SQL Client、開源或商業 BI 工具都支援通過标準 JDBC 的方式連接配接 Hive,可以支援資料探索的動作,極大的豐富了大資料生态圈下的元件多樣性,同時也降低了使用門檻,可以讓熟悉 SQL 的人員低成本遷移。

基于這些設計非常好的特效,加上 Hive 經過這多年的逐漸完善,發展到今天已經是一個非常穩定成熟的生産環境可用的資料倉庫元件,甚至替代品都很難找到,是以使用 Hive 作為資料倉庫的建構基礎是一個非常好的選擇。

看SparkSql如何支撐企業數倉

如上圖所示,其中有很多優點:

  • 穩定:穩定性是 Hive 一個非常讓人稱道的特性,很多時候雖然 Hive 的性能,計算速度不及其他引擎,但是 Hive 的穩定性卻一直是非常好的。
  • 低門檻:隻需要掌握基本的 SQL 技能,便可使用 Hive 進行開發,相比其他分布式計算引擎引擎成本更低。
  • 生态豐富:Hive 和 Hadoop 生态圈緊密結合,而 Hive 自身的 Metastore 也成了大資料生态圈内的标準中繼資料服務,大部分引擎都支援直接适配 MetaStore。
  • 擴充友善:Hive 自身的 UDF 機制可以快速基于業務需要擴充功能。
  • 安全:Hive 支援 Kerberos/LDAP 多種認證方式,并且和 Ranger 結合可以做到更細粒度的行列權限級别,擁有較好的資料安全。
  • 內建成本低:MapReduce 隻支援程式設計态的接口,并且不支援疊代計算,Hive 封裝了 MapReduce 提供 SQL 的接口,可以很低成本的和上層資料挖掘,資料分析工具進行內建。

是以雖然 Hive 出現已經非常有很長時間了,但是依舊是數倉建構的首選,在整個數倉建構中随處可見 Hive 的身影。雖然 Hive 有種種優點,讓人難以割舍,但是并不等于能很好的支撐企業業務需求。很多時候選擇 Hive 僅僅是因為暫時沒有其他可選的元件,如果自己從頭開發一個,或者基于某個元件改造,成本又會遠超企業預期,是以不得不繼續選擇使用 Hive。

基于實踐來看,Hive 在建構企業數倉過程中存在的主要局限圍繞在以下幾個方面:

  • 性能:Hive 基于 MapReduce 雖然帶來了非常好的穩定性,同時也降低了它的性能,雖然有 TEZ 做一定的優化,但是與同類的計算引擎 Spark 相比依舊有非常大的差距。
  • 資源配置:由于 Hive 底層使用 MapReduce 作為計算引擎,而 MapReduce 對 SQL 不友好,是以 Hive 在 HiveServer2 層面實作了 SQL 的轉換處理,再生成基于 MapReduce 的實體計劃,進而導緻 HiveServer2 需要非常高的配置,才能維持足夠好的穩定性。
  • 并發:Hive 的并發受限于 HiveServer2,企業需要維護多個高配的 HiveServer2 執行個體才能支援更好的并非,通常 Hive 的瓶頸都在 HiveServer2 而不是更底層的分布式計算。
  • 容錯成本:Hive 基于 HiveServer2 進行 SQL 的分析處理,多個 HiveServer2 之間互相獨立不共享資訊,是以當 HiveServer2 挂掉後,整個 HiveServer2 的任務都會結束,需要用戶端自行重試,為整個作業級别的容錯重新開機。
  • 事務支援:Hive 的事務設定在 HiveServer2 上,一旦 HiveServer2 執行個體開啟事務後,整個通過該 HiveServer2 的請求都會開啟事務,整個事務成本過高。
  • 部署:如果企業的計算引擎部署是基于 K8S 等容器架構,Hive on K8S 将會帶來非常大的部署成本。

雖然 Hive 在以上局限層面也做了很多嘗試,Hive On Spark,但是受限于 Hive 的架構,HiveServer2 自身有自己的 SQL 解析引擎,為了相容架構将解析後的結果直接翻譯成 Spark 最底層的接口,整體性能反而提升不大。

除了 Hive 之外,還有非常多的其他優秀的元件,但是從企業數倉技術選型的視角來看,适合用來建構資料倉庫的,目前隻有 Hive 和 Spark SQL 相對更加合适,在這兩個元件中,Spark SQL 相對 Hive 的優勢又更加明顯。

SparkSQL 如何支撐企業級數倉

Spark 引擎因為自身強大的生态和友善的程式設計接口被廣泛應用在資料處理場景下,Spark 提供的 Spark SQL 子產品更是将使用 Spark 支撐企業資料倉庫提供了一個良好的基礎設施。

看SparkSql如何支撐企業數倉

如上圖所示,一個典型的資料倉庫架構需要包含不同層次的模型建構。由于資料量大,資料結構異構等多種原因,大資料架構下的企業數倉建構抛棄了基于關系型資料庫下的 Cube 設計,直接采用基于分布式任務進行處理來建構多層資料模型。是以對于建構企業數倉的服務來說,有着如下要求:

  • 支援長時任務,通常是小時以上,天級别居多。
  • 支援多任務,也就是高并發。
  • 穩定性必須被保障。
  • 速度快。
  • 支援 SQL 的互動式接口。
  • 易于內建。
  • 支援任務的重跑和容錯以及快速任務失敗恢複。

基于以上特性可以發現,在目前可選擇的元件範圍内,Spark SQL 相比其他元件,乃至 Hive 更加合适承擔這類任務。但是很多企業在進行架構設計的時候割舍不掉 Spark SQL 帶來的豐富特性,又愁于 Spark SQL 缺乏類似 Hive 這樣的 SQL 伺服器,于是退而求其次變成 Hive 與 Spark SQL 兩個元件共存的形态,Hive 退化為僅僅提供 MetaStore 服務,是以從很多實踐的現象來看,Hive 建構企業數倉已是過去式,采用 Spark SQL 進行資料倉庫的建構是衆多的選擇。

看SparkSql如何支撐企業數倉

如上圖所示,企業在建構數倉的時候,通過一個 Spark SQL Server 提供基于 SQL 接口的常駐服務,同時也可以采用 Spark Submit 的方式直接送出 Jar 任務去運作,既能達到提供标準 SQL 互動式接口,又能提供更靈活的程式設計态接口。

從不同的企業級數倉建構視角來看,Hive 帶來的限制都越來越大,而 Spark SQL 的成熟度和發展趨勢已經完全具備取代 Hive 來建構整個數倉,Spark SQL 的優勢集中展現在如下方面:

  • 豐富的生态:Spark 不僅可以和很多元件內建,其自身擁有生态已經涵蓋各個方面,從資料分析到機器學習和圖計算。
  • 開放:Spark 架構設計上非常開放,可以快速整合其他産品,例如相比 Hive,在內建 Iceberg,Hudi 等特性方面就會開放很多。
  • 部署:Spark 既可以部署在 ECS 虛拟機上,也可部署在 K8S 架構上,多種部署形态非常靈活。
  • 性能:Spark 的機制的流批處理性能非常合适用來建構企業數倉。
  • 易于開發:Spark SQL 既有 SQL 接口,也支援靈活的可疊代程式設計接口,非常友善不同場景下的資料開發。
  • 安全:Spark SQL 可和不同的安全服務內建,實作細粒度的鑒權。

是以,完全基于使用 Spark SQL 來支撐企業級的數倉是完全可行的,并且在目前也被衆多企業實踐驗證。

看SparkSql如何支撐企業數倉

如上圖所示,一個基于 Spark SQL 建構的企業數倉架構邏輯架構設計上包含以上幾個部分,每一個 Spark SQL 引擎都是一個伺服器,Spark SQL 引擎将自己的資訊注冊到 Zookeeper 中,SQL 伺服器基于 Zookeeper 中的 Spark SQL 引擎來執行用戶端過來的請求,SQL 伺服器是一個相容 Hive JDBC 接口的伺服器,在使用 Spark SQL 來支撐數倉建構的時需要重點考慮的實施點是:

  • 如何提供一個互動服務用來支撐不同的用戶端來連接配接,包括互動式的 beeline,以及程式設計态的 JDBC 和工具接口。
  • 如何打通權限對接,如果是 Ranger 的話需要的是 Spark SQL Ranger Plugin。
  • 如何支援跨多個隊列的任務送出。

使用 Spark SQL 支撐企業級數倉的核心的地方還是在于如何提供一個好用的任務伺服器,用來支撐任務的管理。任務管理伺服器在邏輯上與 HiveServer2 相似,但是更加的輕量,沒有 HiveServe2 中複雜而繁重的 SQL 解析,同時又沒有 Spark Thrift Server 這種自身就是一個 YARN 作業的限制。企業可以基于自身的業務流程,開發一個輕量的伺服器,在這方面位元組有非常深的實踐經驗,同時也有自己的 Spark SQL 引擎伺服器,可關注後續的動态。同時業界也有其他企業做了類似的工作,例如網易開源的 Kyuubi。

看SparkSql如何支撐企業數倉

Kyuubi 整個架構圖如上所示(圖檔來自于 kyuubi 官網:https://github.com/apache/incubator-kyuubi)。

Kyuubi 基于 Spark SQL 之上,較好的彌補了 Spark Thrift Server 在多租戶、資源隔離和高可用等方面的不足,是一個真正可以滿足大多數生産環境場景的開源項目。但是 Kyuubi 在設計的時候考慮的是如何彌補 Spark Thrift Server 的不足,目的在于增強 Spark SQL 的能力,而不是對等設計一個可以替換 Hive 元件的服務。是以對于遺留項目來說遷移成本較高,Spark SQL 與 Hive 有着兩套不相容的 SQL,在使用 Kyuubi 的時候如何是遺留系統遷移成本将是一個非常大的工作量。

而行業也有開源的 Spark Thrift Server,該思路是非常優秀的,但是因為開發過程中有點太過于局限,導緻依舊存在很多問題,主要展現在:

  • Driver 單點:整個 Spark thrift server 以一個 Spark 任務的形式運作在 YARN 上,所有的請求都運作在一個 Driver 中,一旦 Driver 挂掉後,所有任務都會同時失敗。
  • 資源隔離:因為 Spark thrift server 是以 Spark 任務的形式運作在 YARN 上,是以送出的任務如果有跨隊列送出需求的時候,Spark thrift server 很難支撐,其次多個任務運作在同一個 Driver 之中,資源使用會互相影響,很難更精細化的進行資源的管理。
  • 多租戶:Spark thrift server 從請求層面是可以支援多使用者的,但是從架構層面來看 Spark thrift server 是一個運作在 Yarn 上的任務,它也有自己的 Application Id 有自己的任務送出者,是以它實際上是以一個超級管理者的身份運作,再做二次租戶隔離,必然存在一定的資源安全問題。
  • 高可用:Spark thrift server 本身是沒有高可用涉及的,是以它的高可用需要自行單獨設計,且還得考慮用戶端的相容,例如 Hive JDBC 将 HA 資訊存儲在 ZK 中,而 Spark thrift server 沒有這樣的機制,是以高可用的實施成本較高。

是以雖然 Spark 提供了 Spark thrift server 服務用來提供類似 JDBC 這樣的接口互動方式,但是目前依舊缺乏很多生成功能,導緻在生産環境使用的情況非常少,Spark thrift server 更像是一個小衆的半成品,小修小補的嘗試着解決部分問題,但是沒有給予一個徹底的方案,導緻現在有點缺乏實際的生産應用。

位元組跳動EMR産品在 Spark SQL 的優化實踐

資料湖引擎內建

Hudi,Iceberg 等資料湖引擎目前使用的越來越廣泛,位元組内部在使用 Spark SQL 的時候也存在需要使用資料湖引擎的需求,是以需要将資料湖引擎內建到 Spark SQL 中,這個過程碰到非常多的問題。

首先在與 Iceberg 內建的時候,對體驗和易用的問題進行了優化,使用者在使用 Spark SQL 過程中,需要手動輸入很多指令,并且需要找到對應的 spark-iceberg 依賴包,這個也是目前內建 Iceberg 最常用的方案。我們的解決方式是在預先安裝的過程中,提前把 iceberg 的相關 jar 包放到 spark jars 目錄下,這樣使用者隻需要指定 catalog 即可,無需再手動輸出很多指令。

其次在 Spark 與 Hive 跨引擎分析場景下使用 Iceberg,Spark 正常建立表,Presto/Trono 可以正常讀寫,但 Hive 無法正常讀寫,這個問題官方的文檔也沒有清晰的描述,解決方案是需要修改 Spark 的配置檔案或者修改 Hive 的 hive-site-spark override 配置,確定初始化出來的 Spark Session 中的配置項 iceberg.engine.hive.enable 的值為 true,Hive 才能正常的讀取 Spark 建立的表。

看SparkSql如何支撐企業數倉

問題上本質上是由于 Iceberg 為了支援 Hive 引擎,在整體的設計上做了一些妥協,使用了 Storage Handler 的方式去實作 Hive 對 Iceberg 格式的表的讀寫,需要顯式的指定 Hive 的 Input/Output Format 實作,而 Presto/Trono 則可以基于 Hive 的 format_type 自動識别表的格式進行識别。

在相容性上,由于 Iceberg 0.12 版本不支援 Spark 3.2,由于更新 Spark 的影響範圍非常大,于是更新了 Iceberg,使用了社群的一個 master 的 snapshot 版本進行編譯,與 Spark 3.2 進行內建。

Spark SQL 伺服器

雖然行業針對Spark SQL 提供一個SQL 伺服器已經有Spark Thrift Server或者Kyuubi這樣的工具,但是在某些B端客戶的業務的背景下,這些工具并不能完全滿足要求,是以位元組跳動EMR團隊自己設計實作了Spark SQL Server,主要聚焦解決的是如下場景:

  • 相容 Hive 語義:由于位元組早期也是基于 Hive 建構的資料倉庫,後續逐漸全部替換為 Spark SQL,中間必然面臨大量的系統遷移,而由于 Hive 與 Spark SQL 語義不盡相同,重寫 SQL 實作的工作量非常大,是以在位元組的 Spark SQL Server 中實作 Hive 語義和 Spark SQL 語義的相容,在實作方案上采用的時候講 Hive SQL 解析注入到 Spark 引擎中,形成一個 SQL Parser Chain,最終會比對到某一個解析器,實作對 SQL 的解析,進而達到對整個 SQL 語義的相容。
  • 提前初始化 Spark SQL 引擎:在業務請求到達前提前在 YARN 上送出 Spark 任務,初始化資源資訊,讓整個引擎處于等待的狀态,可以減少任務送出消耗的時間,在使用者較多的情況下可以提示整體的任務執行時間。
  • 跨 Yarn 隊列的任務送出:使用者可以指定 Yarn 隊列執行任務。
看SparkSql如何支撐企業數倉

如上圖所示,SQL 伺服器是一個實作了 Thrift 接口的伺服器,提供标準的 JDBC 通路接口,Spark SQL 引擎同樣實作了 Thrift 接口,Spark SQL 引擎在服務啟動的時候便已經被送出至 Yarn,處于等待狀态。當業務任務到達的時候,由 SQL 伺服器實作引擎的篩選,比對一個已經存在的引擎,或者重新送出一個全新的引擎用來執行任務。

SQL 伺服器支援 OpenLDAP,Kerberos 等常用的權限認證,同時支援多種不同的隔離級别,例如 Session 級别則每一個業務 SQL 都會初始化一個 Spark SQL 引擎用來接收任務,任務執行結束後,引擎從 Yarn 中銷毀。而 User 級别則針對使用者會初始性 0-N 個引擎,常駐于 Yarn 中,處于交替執行任務。

這樣的伺服器設計打破了 Spark Thrift Server 的單 Driver 所帶來的局限,解耦了 SQL 服務和任務執行。也就支援更細粒度的資源管理和跨隊列的任務送出。

同時也相容了 Hive 的接口,使用者可以通過如下方式通路伺服器:

HA 通路連結:

./bin/beeline -u jdbc:hive2://emr-5fqkwudj144d2gc1k8hi-master-1/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=midas/ha;auth=LDAP -n emr_dev -pEMR123456emr

非 HA 通路連結:

./bin/beeline -u jdbc:hive2://emr-master-2:10005/default;auth=LDAP” -n test_sub -pEMR123456emr

HA 模式下的資訊被記錄在 Zookeeper 中,儲存的内容格式與 HiveServer2 的内容一緻,能確定使用 Hive 的用戶端可以直接通路 HA 模式下的伺服器。

Spark SQL 多租戶

看SparkSql如何支撐企業數倉

在 Hive 任務執行過程中,HiveServer2 服務承擔了提供 SQL 伺服器進行使用者身份認證,權限判斷,以及解析 SQL 生成最終的執行計劃,再由 MR 引擎執行具體的分布式任務。

在這個過程中 HiveServer2 承擔了非常重的職責,是以需要消耗非常大的資源,是以會很大程度的影響使用者的并發。對于分布式任務運作來說,它的資源限制來自于 Yarn 作為資料總管所配置設定的資源,但是在 Hive 架構下卻受限于 HiveServer2 的影響,導緻使用者并發的數量無法随着 Yarn 資源的提升進行提升。

而在 Spark SQL 引擎中,SQL 解析是下推到引擎内部,與具體的分布式任務執行合為一體,不需要單獨的伺服器去做 SQL 解析。也正因為 Spark SQL 與 Hive 在解析子產品的架構存在差異,Hive On Spark 的模式會變得非常難。

針對如上的場景,位元組跳動重新設計的 SQL 伺服器隻負責任務的接收,進行使用者資源,權限和身份的判斷,然後将任務發送給運作在 Yarn 中的 Spark SQL 伺服器。打破了 Hive 這種并發受制于 HiveServer2 和 Yarn 兩層限制的局面,隻由 Yarn 的資源決定使用者的并發程度,進而極大的降低了 Spark SQL 伺服器的資源需求,增強了其穩定性,在使用者并發上有了非常大的提升。

其次通過引擎預熱的功能減少任務執行的時間,提升整體速度,引擎預熱指的是在服務啟動的時候便向 Yarn 送出 Spark SQL 引擎,處于等待的狀态,當業務請求到達的時候,基于業務類型從已經處于就緒的引擎中選擇一個引擎來執行任務。

看SparkSql如何支撐企業數倉

并不是每一個預熱送出的引擎都會被選擇執行,在 SQL 伺服器中存在如下三種引擎隔離級别:

  • Session:基于每一個 connection 都會全新送出 Spark SQL 引擎,在連結斷開後,引擎從 Yarn 上銷毀。
  • User:同一個使用者可以共享多個 Spark SQL 引擎,具體的 Spark SQL 引擎個數由該使用者送出的任務資源需求決定,引擎在連接配接斷開後不會銷毀,直到引擎空閑時長到達上限。
  • Open:所有使用者都可共享的 Spark SQL 引擎,通常是用來應對大賬号,或者叢集不需要做權限管理的場景。

由此可見隻有在 User,Open 的級别下引擎預熱才會産生價值,預熱省去了 Spark Submit 的時間,當使用者數量足夠多,群體為統計機關所節省的時間越多。

Spark SQL 事務支援

Hive 的事務力度是基于 HiveServer2 實作的,例如通過如下文法:

CREATE TABLE tm (a int, b int) stored as orc TBLPROPERTIES ('transactional'='true', 'transactional\_properties'='insert\_only')

可開啟事務,但是由于對事務的管理是在伺服器上,是以需要開啟 ACID 的時候受影響的是整個 HiveServer2 的所有請求,而 Spark SQL 很好的內建和支援了 Hudi,Iceberg 等資料湖格式,是以在 Spark SQL 伺服器中不需要實作類似 HiveServer2 的事務機制,隻需要在最終讀取處理資料的時候,采用 Hudi,Iceberg 等特性便可達到支援事務的效果。

例如對于 Icdberg 資料格式的表已支援 update、delete 操作:

MERGE INTO prod.nyc.taxis ptUSING (SELECT * FROM staging.nyc.taxis) stON [pt.id](http://pt.id) = st.idWHEN NOT MATCHED THEN INSERT *;

是以當 Spark SQL 內建了 Iceberg 後,便具有了事務能力,再配合 SQL 伺服器,便可在很低的成本上具有和 Hive 事務能力同等的效益,同時也沒有 Hive 下的一些限制,從這樣的架構設計上來看,能夠完整的替換 Hive。另外一個方面當使用者數量變多,同時資料會發生修改,更新等操作,很容易造大量的小廣播傳輸,進而引起 Driver 的 OOM。雖然大廣播也會存在 OOM 的問題,但是大廣播可以通過門檻值控制,而小廣播門檻值對其不生效,一旦說數量變多,很容易引起 Driver 的 OOM。

位元組跳動資料平台EMR團隊通過對小廣播進行合并廣播,解決大量小廣播進行傳播,導緻打爆 Driver 的情況出現。

尾聲

随着企業的業務發展越來越複雜,需要更加靈活,更加高效的數倉架構,在這樣的業務驅動背景下,Hive 的局限變得越來越明顯,而基于 Spark SQL 靈活建構數倉的方案将會變得越來越主流。是以企業在考慮資料倉庫建構體系的時候,可以考慮如何基于 Spark SQL 建構自身資料體系,Spark 完善和開放的生态在未來必然會有更多優秀的服務會圍繞 Spark 形成強大的優勢。

我們基于企業級數倉建設的部分經驗技術也已經通過火山引擎E-MapReduce對外開放。

歡迎關注位元組跳動資料平台同名公衆号