導讀:本文是貨拉拉大資料引擎負責人楊秋吉在 DataFunSummit 2022 多維分析架構峰會上的演講分享,分享的主題是《貨拉拉基於 Apache Doris 的 OLAP 體系演進及建設方法》,詳細講解了貨拉拉從 OLAP1.0 到 3.0 的演進過程,其中不乏有值得借鑑的方法論以及深刻的技術思考,希望能對大家有所幫助。
分享人|貨拉拉大資料引擎負責人 楊秋吉
業務背景
貨拉拉成立於 2013 年,成長於粵港澳大灣區,是一家從事同城、跨城貨運、企業版物流服務、搬家、汽車銷售及車後市場服務的網際網路物流公司。截至 2022 年 4 月,貨拉拉的業務範圍已經覆蓋了國內 352 座城市,月活司機達到 58 萬,月活使用者達到 760 萬,包含 8 條以上的業務線。
貨拉拉大資料體系為支撐公司業務,現在已經成立三個 IDC 叢集、擁有上千臺規模的機器數量,儲存量達到了 20PB、日均任務數達到了 20k 以上,並且還處在快速增長的過程中。
大資料體系
貨拉拉大資料體系從下往上分為 5 層,最下面的是基礎層和接入層,這兩層主要會提供基礎資料的儲存、計算以及叢集的管理功能。在基礎層和接入層之上是平臺層和數倉。在平臺層之中包含了資料研發平臺和資料治理平臺,基於平臺層的能力和資料倉儲的資料體系,在這之上面包含了含有業務屬性的服務層和應用層。整個體系自下而上相互支援,實現支援業務和賦能業務的能力。
圖1.1 貨拉拉大資料體系
資料處理流
貨拉拉典型的資料處理流,可以分成資料整合、採集、資料的儲存計算、資料服務四部分,同時也包含了實時、離線以及線上三大業務場景。
圖1.2 貨拉拉大資料資料流
在資料採集階段會存在實時採集和離線採集兩條路線。
- 實時採集比較典型的場景為使用者端上埋點會直接同步到大資料平臺做儲存,供後續的線上和離線計算使用。
- 離線的資料主要是來自於業務方的資料庫,會透過天或者是小時定期採集到大資料儲存中,以供後續使用。
中間是資料的儲存和計算階段。在離線場景中會透過對資料 ETL 之後轉換為構造數倉的分層體系。實時比較典型的場景為資料在經過 Flink 的處理後會直接落線上儲存系統,類似於 HBase 和 OLAP 等等,為後續的業務系統提供資料服務。
OLAP 演進概覽
貨拉拉從 2021 年開始進行 OLAP 的技術研究,截至目前已經經歷 3 個階段:
- 2021 年上半年為貨拉拉的 OLAP1.0 階段,這個階段我們主要是支援公司的羅盤業務,我們引入的是能夠提供較好的單表依據和查詢能力的 Apache Druid 引擎。
- 2021 年下半年為貨拉拉的 OLAP2.0 階段,我們支援了智慧定位工具,這個階段引入了夠提供單表明細查詢,並且還有較高的壓縮率 ClickHouse。
- 今年為貨拉拉的 OLAP3.0 階段,伴隨著公司業務需求的不斷增多,我們也會需要用到多資料來源的關聯分析。基於此,由於 Apache Doris 具備大表關聯分析的能力,我們引入了 Apache Doris 引擎。
圖2.1 貨拉拉OLAP體系演進過程
OLAP1.0 孕育期
業務需求分析
先看下沒有引入 OLAP 之前的業務資料流:
圖3.1 OLAP1.0業務場景
根據該圖可以看到業務的資料透過實時和離線處理之後會落在 MySQL,MySQL 之中儲存了維度聚合之後的結果資料,這也意味著會在 Flink 之中做大量的聚合分析,根據業務需要的相應維度所做的一系列組合都是在Flink之中做實時聚合,最後將結果儲存到 MySQL。
存在的問題:
- 存在儲存瓶頸,類似於 Kylin 之中的維度爆炸的問題。
- 開發成本、高效率低。當業務側需要新增維度的時候會需要對 Flink 中的所有作業都做一定的修改,然後再重新上線。
- 無法支援部分聚合需求。
對於存在的這些問題,我們經過分析之後,總結出了 3 個背後存在的需求點:
- 業務側希望能夠橫向擴容,解決儲存瓶頸。
- 希望能夠自由組合維度做分析,提升業務側開發效率。
- 希望能夠支援任意維度實現跨度的分析。
解決方案
根據業務需求,並透過調研,我們決定使用 OLAP 引擎來支援業務需求。那我們如何選擇一款 OLAP 引擎,並把它穩定的應用到生產之中呢?
我們總結了如下的 4 個步驟作為解決思路:
圖3.2 OLAP 1.0 解決思路
技術調研
技術調研階段,我們對比了 Durid、ClickHouse、Kylin、Presto 和 Doris 等等引擎。結合我們上述的 3 個業務需求,最終我們選擇了 Druid 引擎。
原因是 Druid 除了能夠滿足我們的業務需求之外,還有一個比較重要的影響因素是 Druid 引擎是純 Java 開發,與我們的技術棧比較吻合,可控性更高。
圖3.3 OLAP1.0技術調研
POC 階段
POC 過程中,從以下 3 個步驟著手:
- 功能驗證。在功能驗證中,我們會收集業務側的 SQL,之後提取 SQL Pattern,然後再根據 Druid 引擎的 Rollup 語義做 SQL 的改寫,涉及到大量 UDF 的改寫、Rollup 語義相容以及 Count Distinct 語義相容等等。
- 效能驗證。我們會直接採用業務真實的資料和業務真實的 SQL 來執行。驗證過程中我們會將 Cache 關閉,分別統計 P75、P90、P99 的查詢耗時。在這過程中,我們會發現有部分查詢的效能沒有達到要求,之後我們會做效能分析。Druid 引擎本身沒有比較完善的效能分析工具,不能夠很好的列印出它的執行計劃以及各個運算元的耗時,所以我們採用了第三方的 Arthas 火焰圖進行分析。定位了相應的運算元後,最終我們透過最佳化我們建表導數的邏輯以及索引構建的邏輯,並主要透過調整 Segment 大小的同時加入物化檢視的方法,進行一些引數的調整以此來最佳化效能。
- 準確性驗證。我們將業務真實資料同時寫 Hive 表和 Druid,之後跑 Hive SQL和 Druid SQL,來進行資料質量的校對。在這個過程中我們會發現例如 StringLast 函式等一些函式會在特定的場景下出現計算值不穩定的問題。
圖3.4 OLAP1.0 POC 驗證
穩定性保障
當 POC 驗證完成之後,接下來我們會進行穩定性的保障。我們將穩定性保障分為事前、事中、事後 3 個階段:
圖3.5 OLAP1.0 穩定性保障
上線階段
當穩定性保障建立完成之後就會進入到上線階段。上線過程我們同樣分成了 3 個階段:
- OLAP測試階段。在這個階段中,業務的資料會接入到 Druid 之中,但是業務的真實查詢還是透過原來的 MySQL 庫。這個階段主要會驗證 Druid 引擎的資料質量和 Druid 叢集的穩定性。
- 上線觀察階段。在這個階段,業務的查詢會切回到 Druid。同時舊的 MySQL 鏈路還沒有下線,業務側能夠隨時切回 MySQL 鏈路。
- OLAP執行穩定階段。我們會把 MySQL 舊的鏈路下線,做資源的回收。
圖3.6 OLAP1.0 上生產
問題總結
下面總結了 1.0 階段時遇到的問題:
- 資料匯入部分中,實時資料亂序為典型問題。
- 在資料準確性驗證階段發現 StringLast 的函式值不穩定。
- Durid 沒有一個高效的精準去重的函式。
圖3.7 OLAP1.0 問題總結
OLAP2.0 完善期
業務需求分析
在 OLAP2.0 階段主要有以下 4 個業務需求:
圖4.1 OLAP2.0 業務需求分析
下圖是簡單的業務工具的截圖,從圖中可以看到,OLAP2.0 需要能夠支援彙總與明細,同時基於這些能力能夠做一個快速的問題定位。
圖4.2 OLAP2.0 業務需求分析驟去實現。
解決方案
圖4.3 OLAP2.0 技術調研
OLAP2.0 我們引入了 CliclkHouse。ClickHouse 能夠比較好地支援複雜的資料型別,同時因為業務側是埋點資料,所以對於實時匯入語義要求並沒有那麼高。
沒有采用 Druid 主要是有 2 個原因:
- Druid 對於複雜的資料結構支援度並不是很好。
- Druid 雖然能夠支援明細查詢,但是 Druid 的明細查詢和聚合查詢得分成不同的表,這樣就會額外的引入一系列的儲存成本。
剩下的部分就是 POC 、上生產的步驟,這兩個步驟和 OLAP1.0 階段比較類似,所以在這裡就不過多展開介紹。
OLAP3.0 成熟期
業務需求分析
2022 年隨著公司業務的發展,更多的產品線對於多資料來源關聯場景下的線上分析需求也會變得越來越迫切。比如說 AB 實驗場景與實時數倉場景,這兩個場景對於多表關聯需求,尤其是大表的多表關聯需求也變得越來越迫切。
圖5.1 OLAP3.0 需求分析
舉一個 AB 實驗的例子。從下圖可以看到,例子中是需要把 AB 實驗的一個資料和後面相應的司機與使用者的埋點資料關聯到一起並做分析。在這種情況下,我們就會發現之前的兩種工具都會存在一系列的弊端。
圖5.2 OLAP3.0 需求分析
解決方案
技術調研
在技術調研階段我們觀察了 Druid 和 ClickHouse。Druid 引擎可以支援一些維表的簡單 Join,ClickHouse 則能夠支援 Broadcast 這種基於記憶體的 Join,但是對於大資料量千萬級甚至億級的一些表的 Join 而言,ClickHouse 的效能表現不是很好。
圖5.3 OLAP3.0 技術調研
接下來我們對 Doris 進行了調研,我們發現 Doris 是能夠支援小表的 Join,對大表的話也同樣能夠支援基於 Shuffle 的 Join,對於複雜資料型別(Array、JSon)的支援,經過跟 Apache Doris 社群溝通,預計將在 2022 年 7 月份的新版本中釋出。透過在多個維度和需求滿足度上進行對比,我們最終選擇了 Apache Doris,也是因為 Apache Doris 的 SQL 支援度非常的完善。
圖5.4 OLAP3.0 技術調研
POC 階段
我們除了引用業務真實的資料和場景做驗證以外,還引入了 TPC-DS 的資料集做了驗證。
在多表關聯的場景下對單天資料進行查詢,對 5 億左右的資料量進行 Join,TP75 大概是 9 秒左右。在資料質量階段我們也是把 TPC- DS 的資料集以及業務真實資料集,分別在 Hive 和 Doris 裡面做了雙跑驗證,發現兩者都是能夠完全對得上的。
圖5.5 OLAP3.0 POC
穩定性保障
與之前一樣依然是從事前的容量評估和壓測、事中的監控和定位來進行。
圖5.6 OLAP3.0 穩定性測試
下面是我們的監控圖,主要是關於 Compaction 相關的一些監控,感興趣的同學可以看看。(文末 QA 環節有部分講解)
圖5.7 OLAP3.0 穩定性監控
問題總結
第一個問題是查詢效能的最佳化。
業務側的需求為 7 天的查詢 RT 需要在 5 秒內完成,在最佳化前,我們發現 7 天的查詢 RT 是在 30 秒左右。對於這個問題,我們的主要最佳化策略是把小表 Join 大表改成了大表 Join 小表,主要原理是因為 Doris 預設會使用右表的資料去構建一個 Hashtable。
還有類似下圖中的情況:union all 是在子查詢中,然後再和外層的另外一張大表做 Join 的查詢方式。這種查詢方式沒有用到 Runtime Filter 的特性,因此我們將 union all 提到子查詢外,這樣就能夠用到 Runtime Filter,這應該是由於這裡的條件下沒有推下去所導致的。同時執行時採用的 Bloom Filter 是可以將 HashKey 條件下推到大表 Scan 階段做過濾。在經過對這兩者最佳化之後便能夠滿足我們的查詢效能需求了。
圖5.8 OLAP3.0 問題1
第二個問題是 UnhealthyTablet 不下降,並且在查詢階段會出現 -230 的報錯。
這個問題的場景是我們在沒有停 FIink 寫任務的時候,對 BE 機器交替重啟,重啟完會出現很多 UnhealthyTablet。經過我們後續的分析發現,其中一個原因主要是在 Coordinator BE 在做二階段提交的時候比較巧合,Coordinator BE 的二階段提交 Commit 後,也就是大部分的副本是已經 Commit 後且在 Publish 前,在這短短的時間範圍內 BE 機器被重啟,這也導致會出現 Tablet 狀態不一致的情況。同時由於我們當時把引數調整的過大,導致了 Compaction 壓力過大。
最後的解決辦法:與 Aapache Doris 社群的同學經過互助排查,引入了社群 1.1.0的 Patch,同時對相應的資料做了恢復。
圖5.9 OLAP3.0 問題2
引數最佳化
- 開啟 Profile。Doris 對於查詢的效能分析具有非常好的 Profile 檔案,這一點是非常讚的!我們可以看到各個運算元在每一個階段查詢耗時以及資料處理量,這方面相比於 Druid 來說是非常便捷的!
- 調大單個查詢的記憶體限制,同時把 BE 上的執行個數由 1 個調整成為 8 個,並且增加了 Compaction 在單個磁碟下的資料量。對於 Stream Load,我們把 Json 格式的最大的記憶體由 100 兆調整成為 150 兆,增大了 Rowset 內 Segment 的數量,並且開啟了 SQL 級和 Partition 級的快取。
圖5.10 OLAP3.0 引數最佳化
資料流
下圖是使用 Doris 之後的資料流圖:
圖5.11 OLAP3.0 資料流
資料流中,我們在 Flink 中做的事情已經很少了,經過資料簡單的 ETL 後就可以把資料直接灌入到 Doris。經過 Doris 一系列的聚合計算、union 計算以及多表關聯計算之後,業務側就可以直接查詢 Doris 來獲取相關資料。
總結與思考
總結:我們 OLAP 的引進主要還是從業務需求的角度出發來匹配合適的引擎,為業務精細化運維提供技術支援。在這之後,我們也思考了一套較為完善的上線流程及穩定性保證方案,為業務的平穩執行提供能力保障。
思考:我們認為很難有單個引擎能夠富含各種場景。因此在技術選型時,需要針對於需求特點和引擎特點進行合理選擇。
後續規劃
我們希望可以向 OLAP 平臺化發展,透過實現自助化建模的同時在這方面做一些多引擎的路由,使其能夠支援各類聚合、明細以及關聯等場景。
圖6.1 後續規劃 OLAP 平臺化
除 OLAP 平臺化之外,後續我們的引擎演進計劃從高效、穩定和核心演進三部分來進行。
圖6.2 後續規劃 引擎演進
穩定性方面:對 Doris 還要繼續深入核心理解,提供一定的二次開發。另外 Doris 社群的相關原理以及程式碼級別的教程數量十分豐富,這也間接性降低了我們深入 Doris 原理的難度。
核心演進方面:我們發現 Doris 基本能夠覆蓋 Druid 所有場景,因此後續計劃以 Doris 引擎為主,Clickhous 引擎為輔,逐漸將 Druid 的相關業務向 Doris 遷移。
Q&A 環節
Q:剛才講到了後續要從 Druid 引擎遷移到 Doris,要實現遷移的成本有多大呢?
A:遷移成本方面和我們之前的成本是一樣的。我們上線的時候也會採用以下方式:先把業務的資料同時往 Druid 和 Doris 之中寫,寫完之後的業務遷移會涉及一些 SQL 改造。因為 Doris 更加接近 MySQL 的協議,比起 Druid SQL 會更加便捷,所以這部分的遷移成本不是很大。
Q:剛才介紹的第二個場景之中的監控圖都看了哪些指標呢?
A:關於監控圖,我們會比較關注 Doris 的資料匯入。而在資料匯入部分,我們最關注的就是 Compaction 的效率,是否有 Compaction 的堆積。我們現在還是採用的預設引數,也就是 Compaction 的分數就代表它的版本號,所以我們監控的更多的是它的版本。對於這方面的監控,社群也已經有了比較完善的相應技術方案,我們也是參考了社群的技術方案來進行了監控的指標搭建。
Q:從指標上看,Doris 的實時服務線上查詢效能怎麼樣?在資料匯入情況下效能損耗可以從這些指標上看出來嗎?
A:實時匯入方面主要是從 Compaction 的效率來看。結合到我們這邊的業務場景,最多的一張表,單表一天也有 6 億到 10 億的資料量的匯入,也是一張埋點。另外關於峰值,它的 QPS 也是能達到千到萬的,所以匯入這一塊壓力不是很大。
Q:SQL 快取和分割槽快取實際效果怎麼樣?
A:SQL 快取方面效果還好,對於很多離線場景,尤其是首頁這種查詢的資料量而言。比如以昨天或者是過去一個小時之前的這種情況來說,SQL 快取命中率會非常高。分割槽級快取方面,我們分割槽的時間還是設的是小時級,這意味著如果這個查詢裡面涉及到的一些分割槽在一個小時內沒有資料更新的話,那麼就會走 SQL 快取;如果有更新的話就會走分割槽級快取。總體來看效果還好,但是我們這邊命中比較多的還是 SQL 級的快取。
Q:Doris 的查詢匯入合併和快取的 BE 節點的記憶體一般怎麼分配?
A:快取方面我們分配的不大,還是採用的偏預設的 1G 以內。匯入方面我們設計的是 parallel_fragment_exec_instance_num 這個引數,大概在 8G 左右。
Q:可以解釋一下 OLAP3.0 的解決思路嗎?
A:對於 OLAP3.0 方面來說,業務的主要訴求就是大表 Join。除此之外,還有一些類似於匯入的進度一致等等。
在大表 Join 方面,我們也對比了很多的引擎。Druid 這方面就是偏維表;Clickhouse這方面還是偏基於記憶體方面的 Broadcast。正因如此,主要是基於大表 Join 的出發點,我們選擇引入了在 Join 這方面能力更強的 Doris。
Q:Druid、ClickHouse 和 Doris 應該都是近實時的,就是 Near Real-time,他們的寫入不是立刻可見的,是這樣嗎?
A:是這樣的。像 Doris 和 ClickHouse 之前的寫入都是 Flink 直接去寫,我們也沒有完全做到來一條資料就寫一條,都是一個微批次。一個批次最大可以達到 150 兆的資料堆積,寫入一次的時間間隔也是到 10 秒左右,沒有做到完全的實時寫入。
Q:方便透露一下貨拉拉目前 Doris 的叢集的使用情況,比如機器的數量和資料量嗎?
A:我們的叢集數量還不算很多,10 多臺。
Q:對於 Doris 的運維方面,它的便捷性和 Druid、ClickHouse、Kylin、Presto 這些相比,有很好的擴充套件性嗎?
A:我們覺得是有的。第一個是在我們 Druid 方面碰到了一個比較大的痛點,就是它的角色特別多,有 6 種角色,所以需要部署的機器會非常多。另外一點是 Druid 的外部依賴也非常多,Druid 依賴於 HDFS、離線匯入還需要有 Hadoop 叢集。
第二個是 ClickhHouse 方面,我們當時使用的版本對於 Zookeeper 也是有比較大的依賴。另外,ClickHouse 也是偏偽分散式的,有點類似於資料庫的一種分表。Doris 自身就只有 FE、BE,外部依賴會非常少,所以我們從部署的角度同時考慮到 Doris 的橫向擴充套件方面,Doris 的擴縮容也能夠做到自平衡,所以相比而言 Doris 會更好一些。
Q:在實時特徵場景下,分鐘級的資料更新對服務效能要求比較高,可以用 Doris 嗎?能達到 TP99 200 毫秒以下嗎?
A:TP99 能夠否達到200毫秒以下主要和你查詢 SQL 相關。
例如我們這邊的很多涉及到大表 Join 的查詢,涉及的分割槽資料量大概在 10 億量別,業務側對於查詢效能要求是 5 秒以內,透過 Doris 是可以滿足我們需求的。如果是實時特徵這種業務,是否能達到 200 毫秒可能需要經過一輪實際測試才能得到結果。
資料下載
關注公眾號「SelectDB」,後臺回覆 “貨拉拉 ”!限時下載 完整版 PPT 資料!
加入社群
歡迎熱愛開源的小夥伴加入 Apache Doris 社群,除了可以在 GitHub 上提 PR 或 Issue,也歡迎大家積極參與到社群日常建設中來,比如:
參加社群徵文活動,進行技術解析、應用實踐等文章產出;作為講師參與 Doris 社群的線上線下活動;積極參與 Doris 社群使用者群的提問與解答等。
最後,歡迎更多的開源技術愛好者加入 Apache Doris 社群,攜手成長,共建社群生態。
SelectDB 是一家開源技術公司,致力於為 Apache Doris 社群提供一個由全職工程師、產品經理和支援工程師組成的團隊,繁榮開源社群生態,打造實時分析型資料庫領域的國際工業界標準。基於 Apache Doris 研發的新一代雲原生實時數倉 SelectDB,執行於多家雲上,為使用者和客戶提供開箱即用的能力。
相關連結:
SelectDB 官方網站:
https://selectdb.com (We Are Coming Soon)
Apache Doris 官方網站:
Apache Doris Github:
https://github.com/apache/doris
Apache Doris 開發者郵件組: