導讀 随着資料湖技術的發展,分析性能成為發揮資料湖效用、挖掘資料價值最大的掣肘。基于一款簡單易用和高性能的查詢分析引擎在資料湖之上建構分析服務,成為新的技術趨勢。在過去一年,通過在資料湖上的諸多性能優化,結合自身的高性能執行引擎和查詢優化器以及 Apache Doris,實作了資料湖上極速易用的分析體驗。本文就将揭秘 Apache Doris 資料湖聯邦分析特性。
全文目錄:
- Apache Doris 湖倉一體的思考
- Apache Doris 資料湖特性揭秘
- 案例分享
- 社群規劃
- Q&A
分享嘉賓|陳明雨 Doris Apache Doris PMC Member
編輯整理|劉步龍 碩磐智能
内容校對|李瑤
出品社群|DataFun
01
Apache Doris 湖倉一體的思考
在介紹湖倉一體之前,先來看一些基本概念。首先是資料庫,它是一個最基礎的概念,主要負責聯機事務處理。随着資料量的增長,出現了資料倉庫,它存儲的是經過清洗、加工以及模組化後的高價值的資料,供業務人員進行資料分析。資料湖的出現,主要是為了去滿足企業對原始資料的存儲、管理和再加工的需求。這裡的需求主要包括兩部分,首先要有一個低成本的存儲,用于存儲結構化、半結構化,甚至非結構化的資料;另外,就是希望有一套包括資料處理、資料管理以及資料治理在内的一體化解決方案。
最後來看一下本文要重點介紹的湖倉一體的概念。資料倉庫解決了資料快速分析的需求,資料湖解決了資料的存儲和管理的需求,而湖倉一體想解決的就是如何讓資料能夠在資料湖和資料倉庫之間進行無縫的內建和自由的流轉,進而幫助使用者直接利用資料倉庫的能力來解決資料湖中的資料分析問題,同時又能充分利用資料湖的資料管理能力來提升資料的價值。
Doris 在設計湖倉一體的方案中提出了四個出發點:
- 第一點是湖倉查詢加速,Doris 作為一個非常高效的 OLAP 查詢引擎,有着非常好的 MPP 向量化的分布式的查詢層,可以直接利用 Doris 非常高效的查詢引擎,對湖上資料進行加速分析。
- 第二點是統一資料分析網關,可以提供各類異構資料源的查詢和寫入能力,使用者利用 Doris,可以把這些外部的資料源,統一到 Doris 的源資料的映射結構上,使用者在通過 Doris 去查詢這些外部資料源的時候,可以提供一緻的查詢體驗。
- 第三點是統一資料內建,首先通過資料湖的資料源連接配接能力,能夠讓多資料源的資料以增量或全量的方式同步到 Doris,并且利用 Doris 的資料處理能力對這些資料進行加工。加工完的資料一方面可以直接通過 Doris 對外提供查詢,另一方面也可以通過 Doris 的資料導出能力,繼續為下遊提供全量或增量資料服務。通過Doris可以減少對外部工具的依賴,可以直接将上下遊資料,以及包括同步、加工、處理在内的整條鍊路打通。
- 最後一點就是更加開放的資料生态,衆多資料倉庫有着各自的存儲格式,使用者如果想要使用一個資料倉庫,第一步就需要把外部資料通過某種方式導入到資料倉庫中才能進行查詢。這樣就是一個比較封閉的生态,資料倉庫中資料除了數倉自己本身可以查詢以外,其它外部工具是無法進行直接通路的。一些企業在使用包括 Doris 在内的一些數倉産品的時候就會有一些顧慮,比如資料是否會被鎖定到某一個資料倉庫裡,是否還有便捷的方式進行導出。通過湖倉一體生态的接入,可以用更加開放的資料格式來管理資料,比如可以用 Parquet/ORC 格式來去存儲資料,這樣開放開源的資料格式可以被很多外部系統去通路。另外,Iceberg, Hudi等都提供了開放式的中繼資料管理能力,不管中繼資料是存儲在 Doris 本身,還是存儲在 Hive Meta store,或者存儲在其它統一進制資料中心,都可以通過一些對外公開的API 對這些資料進行管理。通過更加開放的資料生态,可以幫助企業更快地接入一個新的資料管理系統,降低企業資料遷移的成本和風險。
02
Apache Doris 資料湖特性揭秘
1. 特性一覽
Doris 目前版本已經支援了一些湖倉一體和資料湖加速的功能。
首先是對不同資料源的支援,已經支援了包括 Hive、Iceberg、Hudi 等資料倉庫和資料湖的連接配接。
針對 Hive 支援了包括 ExternalTable、ManagedTable,通過内部代碼改造相容了不同版本的 Hive Metastore,同時也支援針對 Hive Metastore 中存儲的中繼資料進行手動或自動地同步。
Iceberg 方面支援了 V1 和 V2 格式,也支援通過 snapshot 查詢實作TimeTravel,同時也支援了 Iceberg 不同的中繼資料中心,包括 HMSCatalog,RestCatlog、Aws Glue,以及阿裡雲的 Data Lake Formation 等。
Hudi 也是支援了不同的中繼資料存儲,還支援了 copy-on-write 和 merge-on-read。
ES 方面, Doris 在之前版本中就已經支援了 Doris on ES 這樣一個功能,可以基于Doris 分布式的 SQL 查詢能力,直接去查詢 ES 上的資料。第一是提供很好的性能支援,第二是在 SQL 中擴充了一些 Doris 查詢文法,使用者可以通過 SQL 直接去查詢 ES 中存儲的日志資料等。在新的連接配接架構下,也支援了 ES 的 catalog,在原有的基礎功能之上還支援了對 ES 中繼資料的自動全量 index 映射,使用者不用再一張表一張表地去建立映射關系,直接通過一個連接配接指令就可以将 ES 所有的 index 全都同步過來,然後開始進行查詢。
JDBC catalog,可以通過 JDBC 協定去連接配接幾乎所有的可以通過 JDBC 連接配接的資料源,包括 MySQL、PG、Oracle 等。連接配接以後可以自動地把這些資料源中的庫、表等元資訊同步過來,然後就可以開始進行查詢。通過 JDBC 連接配接的好處包括:第一是可以進行快速的對上遊資料庫的資料同步,比如可以通過 insert into select 語句,直接把上遊資料庫中的資料導入到 Doris 中來;第二,可以把這些外部資料源當做維表,和 Doris 中存儲的主資料進行關聯查詢。
Doris 還支援了對檔案的直接分析,使用者可以直接把單個或者一批 parquet 檔案、 ORC 檔案,或者 text 格式的檔案存儲在遠端存儲上,比如對象存儲、HDFS 等,可以通過的 table value function 直接去對檔案進行分析。同時也支援對檔案 schema 的自動推導,也就是使用者在分析檔案的時候,可以直接把檔案當作一張二維表去分析,這樣可以充分利用 SQL 能力,對檔案不入庫地直接分析。
Doris 在資料湖聯邦分析下主要分為兩種場景:中繼資料連接配接和資料通路。接下來将分别具體介紹。
2.中繼資料連接配接
中繼資料連接配接要解決的問題可以總結為四方面:
- 首先是統一的中繼資料結構,主要是為了屏蔽不同資料源中中繼資料的差異,因為不同資料源中中繼資料的層級結構、定義、schema、列類型可能都是不一樣的,需要一個統一的接口把這些異構資料源中的中繼資料的差異屏蔽掉。在 Doris 中都是統一的中繼資料層級和結構。
- 第二是可擴充的源資料連接配接架構。因為外部的資料源非常多,需要通過一個可擴充的連接配接架構來幫助使用者以更低的成本快速接入新的資料源。是以在整個資料連接配接架構上進行了一些抽象,把對外的 API 通過接口的方式暴露出去,這樣開發者在接入一個新的資料源時,可以直接通過接口快速接入。
- 第三是高效的中繼資料通路能力,針對聯邦分析,去查詢外部資料源的時候,通路性能和穩定性都是不可控的。Doris 的中繼資料連接配接架構就是為了在這樣的場景下去提供一個可靠的、高效的中繼資料通路性能。同時也要支援包括中繼資料的實時同步,來幫助使用者能夠更合理有效地去通路外部的元資訊。
- 最後一點是自定義的鑒權服務, Doris 本身有一套自己的鑒權管理能力,包括對庫表列行的權限管理,一個外部資料源也會有自己的權限管理系統,在接入外部資料源的時候,如果隻能用 Doris 内部的權限管理系統,那麼一些企業使用者可能需要切換或重構其權限管理系統。是以實作了自定義的鑒權服務,能夠更靈活對接外部權限管理系統包,比如 Apache Ranger 這樣一個統一的權限管理系統,進而降低業務遷移的成本。
在Doris新版本中引入了新的一個層級,catalog 層級,這樣就組成了一個完整的三層的中繼資料結構,即 catalog 、database、table。
在之前的架構中,沒有 catalog 這一層級的,無法直接去映射一個資料源。比如要連接配接一個 Hive 叢集,在 Doris 中是找不到這樣的一個對應關系去映射的,在原先的版本中,查詢一個 Hive 表隻能是通過一張表一張表地去通過 create external table 的方式,建立中繼資料的映射。如果Hive 中有 1000 張表的話,需要寫 1000 個 create table 語句,是非常困難的。是以在新的架構中引入了 catalog 這樣一個層級,可以直接去映射到外部的資料源,映射隻後,Doris 會自動地把這些庫表的元資訊同步過來,使用者不需要再手動建立映射關系。這樣可以友善地進行資料源的查詢。
建立完元素映射關系以後,可以通過 SQL 語句很友善地進行跨資料源的聯邦通路。比如在上圖的例子中,可以把 Hive 的一張表和Iceberg的一張表進行 join 查詢,得到想要的結果。另外,也提供了可擴充的中繼資料連接配接架構,上圖中給出了一個連接配接 Hive 的示例,也可以連接配接亞馬遜的 AWS Glue、阿裡雲的 Data Lake Formation 等統一的中繼資料服務中心,來友善地接入外部的中繼資料資訊。
對于中繼資料通路,以 Hive Metastore 為例,最原始的一種實踐就是每次的中繼資料通路都直接通路 Hive Metastore,這樣的話開銷是非常大的。是以這裡做了兩件事情,首先是中繼資料的緩存,從上圖左側可以看到,有不同類型的中繼資料緩存,包括 schema 的緩存,分區表的 partition 的緩存,以及 partition 之下具體的 HDFS 或 S3 上檔案資訊的緩存,通過三級緩存可以為 Doris 提供一個非常穩定的中繼資料通路服務。這樣使用者在大部分情況下都可以直接命中本地的緩存資訊,隻有在少部分情況下,比如中繼資料更新的情況下,才會去從遠端拉取最新的中繼資料更新本地的緩存。
第二點就是中繼資料的實時同步。也提供了兩種方案。第一種方案是針對所有的中繼資料服務,都提供手動的重新整理能力。可以通過 refresh 指令,去重新整理catalog 級别、database 級别、 table 級别甚至 partition 級别的中繼資料。使用者可以在外圍起一個定時腳本,每 5 分鐘或者每 10 分鐘進行一次中繼資料的重新整理,實作一個半自動的中繼資料重新整理服務。針對 Hive Metastore,也提供了自動的中繼資料的同步能力。通過訂閱 Hive Metastore 的 Meta change 的 event,來自動地同步 Hive Metastore 中的中繼資料變更,這樣就會達到一種近實時的中繼資料的自動同步。有些使用者可能希望分鐘級,甚至秒級去感覺到外部資料源的同步,可以通過這種方式來實作。這樣對使用者的使用以及對資料時效性來講都是比較友好的。
上圖展示了統一鑒權服務的架構。首先,create catalog(資料源連接配接的時候)可以指定使用哪種鑒權插件, Doris 内部提供了統一的 internal access controller 鑒權插件,通過 Doris 内部的RBAC 機制的權限管理能力,進行庫級别、表級别、行列級别的權限管理。使用者也可以在 create catalog 的時候指定自定義的鑒定插件。比如在内部已經支援了 Apache Ranger 的 Access Controller,指定以後可以直接通過 Ranger 插件去通路 Ranger 中的權限資訊,對整個資料源的通路進行鑒權。這樣在 catalog 級别可以定義不同的鑒權服務。使用者在連接配接外部資料源以後,就可以直接利用他自己的鑒權插件去提供包括授權、審計以及資料加密等一系列操作。
3.資料通路
大部分的數倉或者資料湖的資料都是存儲在外部統一的共享存儲上的,可以簡單分為兩大類,第一類是 HDFS 以及 HDFS 相容的一些存儲系統,第二類是雲上對象存儲。資料通路本質上要解決的問題是如何在這些遠端存儲上進行高效的資料讀取。
資料湖有一個初衷,是通過更開放的資料格式來提升資料的開放性,減少使用者對資料遷移的顧慮。Parquet 或者 ORC 是非常通用的資料格式。
首先就是要優化 Parquet reader。在以前的實作中,是通過 Apache arrow 内置的 C++ 的 parquet reader 進行資料讀取的,但它本身也帶來諸多限制。第一點,它會多一層資料的記憶體格式轉換,資料從檔案中讀取出來以後要先轉換成 Arrow 的格式,再轉換成 Doris 的格式。并且 Arrow 内置的 parquet reader,其功能不是很全面,比如它無法利用 Page Index,也不支援 Bloom Filter,不支援字典編碼。
是以通過 C++ 重寫了一個全新的 Parquet reader,具有如下優點:
- 少了一次記憶體格式轉換,記憶體從檔案中讀取出來以後,直接就轉換成 Doris 内部的記憶體格式;
- 充分利用了 Parquet 的一些新特性,比如 Page Index,可以更精确地過濾無用資料;
- 利用 Bloom Filter 進行資料過濾;
- 支援字典編碼,一條查詢條件可以直接下推到 parquet reader,在 parquet reader 中根據字典編碼,把 with 條件轉換成字典編碼的條件,通過整型的比較來加速字元串比較查詢的效率;
- 支援延遲物化,比如有多個查詢條件和多個需要讀取列的時候,優先讀取那些有查詢條件的列,先進行資料過濾,在過濾之後,通過過濾後的行号再讀取其它的列,這樣能夠大大減少 IO 的開銷。
是以,整個資料通路的一個最基本的初衷,就是盡量減少從遠端存儲中讀取的資料量和讀取頻率,來加速查詢響應。
要減少遠端資料通路,自然會想到的一個優化點就是進行本地檔案 cache。這塊做了兩個工作,第一個工作是支援 Local File Cache,可以針對檔案進行 block 級别的檔案緩存,可以把遠端 parquet 檔案按照 4K 到 4M 的範圍進行檔案塊的緩存。利用 parquet 列存的存儲特性,隻在本地緩存需要讀取的資料,這樣下次再去讀取資料的時候就可以直接讀取本地緩存的檔案。在實際測試中,如果資料完全命中本地檔案緩存的話,可以達到幾乎和内表一緻的查詢效率。
第二個工作是在緩存基礎上去做了一緻性哈希。在做外部資料源的資料查詢的時候,不需要利用到 Doris 本身的 BE 節點的存儲能力,也就是說在 FE端做查詢規劃的時候,可以随機地把查詢任務發送到任意的 BE 節點,然後去做通路。這樣帶來的一個問題就是有可能第一次查詢落到了 a 節點,進行了本地完全緩存,第二次查詢又随機到了 b 節點,而 b 節點沒有緩存,那麼查詢第一次可能很快,第二次又會變慢。是以我們通過一緻性哈希來盡量将查詢規劃到已經存在緩存的節點上,進而保證查詢的穩定性。另外,有無狀态的計算節點可以進行彈性的節點伸縮,在節點上下線的情況下,通過一緻性哈希的算法可以有效地保證在節點變更的情況下,能夠盡量少地去對 file cache 進行遷移,進而進一步降低 Cache Miss 的發生率。
針對 BE 上資料的執行和掃描進行了架構的重構。首先,在接入資料源時,不用再去重新寫一套資料的查詢能力,希望能夠最大程度地利用 Doris 本身已有的資料查詢優化,來加速外部資料的查詢,是以對整個執行節點的執行架構進行了分層的重構。
可以看到在 scan 這一層往下,是針對各個資料源不同的實作,scan 這層往上,所有的查詢規劃都是完全相同的。這樣無論查詢内表還是查詢外表,都可以充分利用整個 Doris的查詢優化的能力,包括查詢優化器的能力,謂詞下推的能力, runtime filter 能力,以及各個算子的優化能力。在 scan 節點之下,也統一了兩個部分,第一個是 scanner scheduler,掃描任務的排程邏輯,以及 scanner thread pool,也就是掃描任務的掃描程序池,通過這兩個統一的管理子產品,可以去做很多事情。可以針對内表和外表進行資源上的管理,比如内表有一個延遲的要求,那可能配置設定更多的資源,外表可能是吞吐的要求更高,可能線程數會更少,但利用的帶寬會更多。通過統一的全局的排程視角,可以去做一些資源隔離。經過改造,隻需要一人/周就可以接入一個新的資料源,整個架構是非常友善的。
上圖可以看到在完成了上述優化後,外表查詢的性能表現。在 ClickBench 寬表場景,以及 TPCH 标準的測試集上,與 Trino 進行了對比,總體上有 3 到 10 倍的性能提升。展現出了 Doris 對外部資料源及湖上資料查詢有着很好的加速能力。
4.負載管理與彈性計算
在查詢外部資料源的時候,其實不需要利用到 Doris 本身的存儲子產品,在丢到存儲子產品以後,BE節點本質上是一個無狀态的節點了,在無狀态節點上就可以很好地做到彈性的節點伸縮,因為不管是加節點還是減節點,不再需要關心狀态的轉移情況,可以很安全地把一個節點删掉或加上來。是以在 BE 節點上目前提供了兩種部署模式。第一種是 MIX 模式,就是原有的模式,既支援計算也支援本地存儲。第二種是compute node 模式,關閉了本地存儲功能,隻有計算能力,可以通過無狀态的 computer node 來快速地對叢集進行彈性伸縮,進而快速承接一些外部資料通路的計算負載。同時也基于一些其它技術,包括 FQDN 功能,來提供 Doris 在 K8S 上的部署支援。
03
案例分享
最後,通過一個案例來介紹 Doris 是如何應用中在實際業務場景中的。
在某金融風控場景,資料存儲在 ES、Hive、GP 中,無法進行有效的資料關聯查詢,并且 Hive 本身 T+1的資料處理能力無法滿足資料時效性的要求。在引入了 Doris 1.2 版本之後,它可以通過 Doris Multi Catalog(資料源連接配接能力)來統一多個資料源的查詢通路。
由此帶來了幾點好處:
首先,多個資料源之間可以通過 Doris 進行統一的聯邦分析。
另外,不用再去把 Hive 中的資料導入到其它系統中進行加速查詢,可以直接使用 Doris 的查詢服務能力,對 Hive 中的資料進行查詢加速,這樣資料時效性有了極大的提升。
第三,為 ES 半結構化資料提供了統一的 SQL 的查詢語義,這樣通過 Doris,統一了它整個風控資料主題數倉的查詢接口,來對外提供服務。
04
社群規劃
Doris 社群之後的規劃主要圍繞更豐富的資料源支援、資料內建、資源隔離與排程三個方面進行。
在資料源支援方面,第一點是支援 Hudi 的 Merge-on-Read,使得在 Doris 中能夠直接讀取Hudi的增量。第二點是在 Doris 中擴充 Iceberg/Hudi 中新資料格式的資料加速能力。第三點是接入更多的資料源,比如 Delta lake,Paimon。其中 Hudi 的 Merge-On-Read 和 Paimon 已經在 2.0 版本支援,歡迎試用。
在資料內建方面,第一點是通過 CDC 能力和增量物化視圖進一步完善複雜資料查詢場景下的加速支援。第二點是 Git Like 的資料通路能力,通過該能力可以很友善地對資料進行管理。第三點是資料的寫回,目前 Doris 是不支援資料寫回操作的,後續在支援了該功能之後,Doris 在絕大部分業務場景下去做完整的外部資料源的管理,包括資料的查詢和寫入。
在資源隔離與排程方面,在 Doris2.0 會引入 pipeline 的執行架構,在執行架構基礎之上,可以進一步地細化資源隔離和任務排程的機制,來保證可以在同一個機器内進行 CPU、記憶體、IO 的隔離,進而幫助使用者更好地去管理這樣的一個 Doris 叢集。
Apache Doris 現在已是全球最活躍的開源社群之一,提供豐富的社群支援。在阿裡雲 EMR、百度雲 Palo、騰訊雲 CDW 都有基于 Apache Doris 的商業化支援。無論是開源的Doris使用者,還是想去購買基于Doris的商業化支援,都可以滿足需求。
最後,歡迎更多開發者加入到 Apache Doris 社群。
05
Q&A
Q1:Doris 能夠無縫替換 Presto 嗎?
A1:無縫替換現在還做不到。一個目标就是去替換 Presto 的一些場景。Doris 的性能名額其實是比 Presto 要更強。當然從功能豐富度來講,與 Presto 還是有一定差距。但是在某些場景下是有優勢的,比如對 Hive 的查詢,或者對 Iceberg 的查詢等等,功能已經相對比較完備了。如果感興趣的話,可以嘗試用 Doris 去替換 Presto 的一些場景。同時我們已經開始支援 Presto 文法的相容工作,感興趣的同學可以聯系社群試用。
Q2:BE 提供的計算能力除了查詢還能寫到數倉和 HDFS 對象嗎?
A2:目前無法直接去寫入,在文中也提到了,這是後續要支援的。目前的做法是把經過加工處理後的資料,通過 select out file 或者 export 的方式,把資料導出成 parquet 檔案或者 ORC 檔案,存儲到對象存儲上或者 HDFS 上。
Q3:Doris 有沒有和 Spark 進行過性能比較,能否在數倉替換 Spark?
A3:沒有和 Spark 進行過直接的性能比較,但是從和 Presto 的比較來看,我們比較有信心會比 Spark 快很多。其次 Doris 的初衷是想去做資料內建和加工,是以也希望能夠代替一些在比較少資料量場景下的 Spark 的功能,進而減少一些中小企業對各個大資料元件維護的困難。比如 GB、TB 級别的資料,可以直接通過 Doris 來完成,不需要借助更加複雜的 Spark 或者 Flink。
今天的分享就到這裡,謝謝大家。