OLAP演進實戰,Druid對比ClickHouse輸在哪裏?


​導讀

 

本文介紹eBay廣告數據平臺的基本情況,並對比分析了ClickHouse與Druid的使用特點。基於ClickHouse表現出的良好性能和擴展能力,本文介紹瞭如何將eBay廣告系統從Druid遷移至ClickHouse,希望能爲同業人員帶來一定的啓發。

 

背景

 

eBay廣告數據平臺爲eBay第一方廣告主(使用Promoted Listing服務的賣家)提供了廣告流量、用戶行爲和效果數據分析功能。廣告賣家通過賣家中心(Seller Hub)的營銷標籤頁、效果標籤頁和公開API,有效掌控和對比店鋪的營銷活動和推廣商品的流量、銷量的實時和歷史數據,並通過網頁或者API 下載數據分析報告。

 

這一系統上線之初使用了自研的分佈式SQL引擎,構建在對象存儲系統之上。3年前隨着廣告流量增加,我們把數據引擎切換到Druid上。

 

這一平臺的主要挑戰如下:

 

  • 數據量大每日的插入數據記錄有數百億條,每秒的插入峯值接近一百萬條;

  • 離線數據攝入:在不影響實時數據攝入的情況下,每天需要對前1-2天的數據進行在線替換。根據上游數據團隊發佈清洗過的每日數據,廣告數據平臺需要在不影響查詢的情況下每日替換實時數據,數據切換要求實現跨節點的全局原子操作;

  • 完整性和一致性:面向賣家的財務數據,離線更新後的數據要求不能有遺漏和重複;實時數據要求端對端的延遲在十秒內。

 

 Druid VS. ClickHouse

 

Druid於2011年由Metamarkets開發,是一款高性能列式在線分析和存儲引擎。它於2012年開源,2015年成爲Apache基金會旗下項目。Druid在業界使用廣泛,爲千億級數據提供亞秒級的查詢延遲,擅長高可用、水平擴展;另外爲數據攝入提供了很多非常方便的聚合、轉換模版,內建支持多種數據源,最快可以在幾十分鐘內配置好新的數據表,包括數據定義和數據攝入鏈路(Lambda架構),大大提高了開發效率。

 

ClickHouse由俄羅斯最大的搜索引擎公司Yandex研發,設計目標是支持Yandex.Metrica(世界第二大Web分析平臺)生成用戶分析報表等核心功能。ClickHouse是一個數據庫管理系統(DBMS),有數據庫、表、視圖、DDL、DML等概念,並提供了較爲完整的SQL支持。其核心特性有如下幾點:

 

  • 高效的數據存儲通過數據壓縮和列式存儲,可以達到最高10倍的數據壓縮率;

  • 高效的數據查詢通過主鍵索引、向量化引擎處理、多處理器併發和分佈式查詢,最大壓榨CPU的所有能力,在中小規模的數據量上尤爲突出;

  • 靈活的數據定義和通過支持SQL語言、JDBC和關係模型,降低學習和遷移成本,可以和其他現有數據的產品無縫集成。

 

 

爲什麼遷移?

 

運維  

 

Druid雖然提供了很多非常方便的數據攝入功能,但它的組件構成也較爲複雜,節點類型有6種(Overload, Coordinator, Middle Manager, Indexer, Broker和Historical)。除了自身的節點,Druid還依賴於MySQL存儲元數據信息、Zookeeper選舉Coordinator和Overlord、HDFS備份歷史數據。

 

ClickHouse的架構採用了對等節點的設計,節點只有一種類型,沒有主從節點。如果使用了副本功能,則依賴於Zookeeper保存數據段的同步進度。

 

與此同時,eBay的基礎架構團隊提出在定製ClickHouse的基礎上,向產品團隊提供列式數據庫存儲的服務。除了運維和生命週期管理,基礎架構團隊對ClickHouse進行改造和二次開發,進一步提高了數據攝入和存儲的效率,並在離線攝入方面彌補了和Druid的功能差距。

 

延時數據插入  

 

Druid通過引入實時數據的索引任務,把實時數據處理成一個個分段數據(segment),並歸檔成歷史數據。成爲分段數據之後,該時段數據即不可寫入。由於併發實時索引任務數的限制,我們設置了3個小時的窗口長度(每個小時一個任務),因此超過3個小時的數據就無法寫入。在某些極端情況下,例如上游數據延遲或者實時數據消費過於滯後,就會導致離線數據替換前這部分數據的缺失。ClickHouse則沒有這個限制,任意分區都可以隨時寫入。

 

主鍵優化

 

 

ClickHouse支持的主鍵並不是傳統意義下關係型數據庫的主鍵。傳統的主鍵要求每條表記錄都有唯一的鍵值,通過查詢主鍵可以唯一地查詢到一條表記錄。而在ClickHouse中,主鍵定義了記錄在存儲中排序的順序,允許重複,所以稱之爲排序鍵似乎更加合理。事實上在ClickHouse裏的主鍵定義通過ORDER BY聲明,僅在個別場景中允許和排序鍵不一致(但必須是排序鍵的前綴)。

 

由於我們的產品是給賣家提供分析功能,幾乎所有的查詢限定在了單一賣家維度,因此通過主鍵按照賣家排序,可以極大地提高查詢效率以及數據壓縮率。

 

系統架構

 

 

 

 

如上圖所示,系統由4個部分組成:

 

  • 實時數據獲取模塊,接入eBay的行爲和交易實時消息平臺;

  • 離線數據替換模塊,接入eBay內部的數據倉庫平臺;

  • ClickHouse部署和外圍數據服務;

  • 報表服務,支撐廣告主、商家後臺和eBay公開API。

 

實戰經歷

 

Schema 設計

 

 

ClickHouse提供了豐富的schema配置。這方面需要根據業務場景和數據模式反覆斟酌和多次試驗,因爲不同的選擇會對存儲和性能有數量級的影響,一個錯誤的選擇會導致後期巨大的調優和變更成本。

 

1)表引擎

 

ClickHouse的存儲引擎的核心是合併樹(MergeTree),以此爲基礎衍生出彙總合併樹(SummingMergeTree),聚合合併樹(AggregationMergeTree),版本摺疊樹(VersionCollapsingTree)等常用的表引擎。另外上述所有的合併樹引擎都有複製功能(ReplicatedXXXMergeTree)的對應版本。

 

我們的廣告數據平臺的展示和點擊數據選擇了複製彙總合併樹。這兩類用戶行爲數據量極大,減小數據量節省存儲開銷並提升查詢效率是模式設計的主要目標。ClickHouse在後臺按照給定的維度彙總數據,降低了60%的數據量。銷售數據選擇了普通的複製合併樹,一方面由於銷售數據對某些指標有除彙總以外的聚合需求,另一方面由於本身數據量不大,合併數據的需求並不迫切。

 

2)主鍵

 

一般情況下,ClickHouse表的主鍵(Primary Key)和排序鍵(Order By Key)相同,但是採用了彙總合併樹引擎(SummingMergeTree)的表可以單獨指定主鍵。把一些不需要排序或者索引功能的維度字段從主鍵裏排除出去,可以減小主鍵的大小(主鍵運行時需要全部加載到內存中),提高查詢效率。

 

3)壓縮

 

ClickHouse支持列級別的數據壓縮,顯著地減少原始數據的存儲量,這也是列存儲引擎的巨大優勢。查詢階段,較小的存儲佔用也可以減少IO量。對不同列選擇一種合適的壓縮算法和等級,能把壓縮和查詢的平衡做到性價比最優。

 

ClickHouse的所有列默認使用LZ4壓縮。除此以外,一般的數據列可以選擇更高壓縮率的算法如LZ4HC,ZSTD;而對於類似時間序列的單調增長數據可以選擇DoubleDelta, Gorilla等特殊壓縮算法。LZ4HC和ZSTD等高壓縮率的算法還可以自己選擇壓縮級別。在我們的生產數據集上,ZSTD算法對String類型字段壓縮效果較爲顯著。LZ4HC是LZ4的高壓縮比改進版,更適用於非字符串類型。

 

更高的壓縮率意味着更少的存儲空間,同時由於降低了查詢的IO量,可以間接提升查詢性能。不過CPU也不是大風颳來的,數據的插入性能就成了犧牲品。根據我們內部測試的數據,在我們的生產數據集上使用LZ4HC(6)相比LZ4可以節省30%的數據,但實時數據攝取性能下降了60%。

 

4)低基

 

值得一提的是,對於基數較低的列(即列值多樣性低),可以使用LowCardinality來降低原始存儲空間(從而降低最終存儲空間)。如果在使用壓縮算法的情況下對一字符串類型的列使用LowCardinality,還能再縮小25%的空間量。

 

在我們的測試數據集上,如果整表組合使用LowCardinality、LZ4HC(6)和ZSTD(15),整體壓縮比大約在原來的13%左右。

 

離線數據替換

 

 

1)挑戰

 

針對廣告主的數據報表要求數據準確、一致。實時的行爲數據存在少量的bot數據(需要離線清除),另外廣告的歸因也需要在離線階段重新調整,因此我們引入了離線數據鏈路,在實時數據寫入24-72小時之後,用離線數據替換實時數據。其中的挑戰如下:

 

  • 廣告系統每天需要處理的用戶離線數據量近1TB,在此之前,需要耗費大量時間將數據從Hadoop導入Druid。另外,導入期間的I/O、CPU和內存的開銷對查詢的壓力不小。如何在保證數據一致性的同時,亦確保數據遷移的效率,是問題的關鍵;

  • 如何在數據替換期間,確保用戶可見的數據波動最小。這就要求數據替換操作是原子性的,或者至少對每個廣告主都是原子的;

  • 除了日常的離線數據更新,在數據倉庫數據出現偏差遺漏時,需要支持大範圍的數據修正和補償。作業調度要求保證日常工作及時完成,並儘快完成數據修正工作。此外還需要監控數據更新中的各種指標,以應對各種突發狀況。

 

Druid原生支持數據離線更新服務,我們與基礎架構團隊合作,在ClickHouse平臺實現了這一功能。

 

2)數據架構

 

對於整合在線數據和離線數據的大數據架構,業界通常的做法是Lambda架構。即離線層和在線層分別導入數據,在展示層進行數據的合併。

 

我們也大致上採用了這一架構。但具體的做法和經典有所不同。ClickHouse裏數據分區(partition)是一個獨立的數據存儲單元,每一個分區都可以單獨從現有表裏脫離(detach)、引入(attach)和替換(replace)。分區的條件可以自定義,一般按照時間劃分。通過對數據表內數據分區的單個替換,我們可以做到查詢層對底層數據更新的透明,也不需要額外的邏輯進行數據合併。

 

3)Spark聚合與分片

 

爲了降低ClickHouse導入離線數據性能壓力,我們引入了Spark任務對原始離線數據進行聚合和分片。每個分片可以分別拉取並導入數據文件,節省了數據路由、聚合的開銷。

 

4)數據更新任務管理

 

A. 鎖定分區拓撲結構

 

在處理數據前,離線數據更新系統向基礎架構團隊提供的服務請求鎖定ClickHouse的分區拓撲結構,在此期間該分區的拓撲結構不會改變。服務端根據預先定義好的數據表結構與分區信息返回數據的分片邏輯與分片ID。離線數據更新系統根據拓撲信息提交Spark任務。多張表的數據處理通過Spark並行完成,顯著提升了數據更新的速度。

 

B. 數據聚合與分片

 

對於每一張需要更新的表,啓動一個Spark任務對數據進行聚合與分片。根據ClickHouse服務端返回的表結構與分片拓撲將數據寫入Hadoop,同時輸出數據替換階段用於校驗一致性的checksum與分片行數。系統通過Livy Server API提交併輪詢任務狀態,在有任務失敗的情況下進行重試,以排除Spark集羣資源不足導致的任務失敗。離線數據更新不但要滿足每天的批量數據更新需求,還需要支持過往數據的再次更新,以便同步上游數據在日常定時任務更新之外的數據變動。

 

我們利用平臺團隊封裝的Spring Batch管理更新任務,按照日期將每天的數據劃分爲一個子任務。通過Spring Batch實現的Continuously Job保證在同一時刻子任務在運行的唯一性,避免產生任務競爭問題。對於過往數據的更新,我們將Batch任務分類,除了日常任務之外,還可以手動觸發給定時間範圍內的數據修正任務(如下圖)。

 

 

C. 數據替換

 

在子任務中的所有Spark Job完成後,離線數據更新系統會調用基礎架構團隊提供的數據替換接口,發起數據替換請求。服務端按照定義好的分區,將數據從Hadoop直接寫入ClickHouse,如圖3所示。

 

 

 

離線數據更新系統的架構如圖4所示。MySQL數據庫用於記錄數據替換過程中任務的狀態與優先級,當Spark Job失敗或者由於其他原因導致替換任務失敗重啓後,恢復任務的進度。

 

 

 

5) 原子性與一致性

 

爲了保證數據替換的原子性,基礎架構團隊提供了分區替換的方式。在離線數據導入的過程中,首先創建目標分區的臨時分區。當數據替換完畢並且校驗完成之後,目標分區會被臨時分區替換。針對不同機器上不同分片的原子性替換問題,基礎架構團隊爲每一條數據引入了數據版本。對於每一個數據分區,都有對應的活躍版本號。直到待替換數據分區的所有分片都成功導入之後,分區的版本號進行更新。上游應用的同一條SQL只能讀取同一分區一個版本的數據,每個分區的數據替換隻感覺到一次切換,並不會出現同時讀取新舊數據的問題。

 

廣告平臺報表生成應用因此在SQL層面引入了相應的修改,通過引入固定的WITH和PREWHERE語句,在字典中查詢出每個數據分區對應的版本號,並在查詢計劃中排除掉不需要的數據分區。

 

爲了確保數據替換的一致性,在完成Spark數據處理之後,離線數據更新系統會計算各數據分片的校驗碼與數據總量。當替換完畢之後,ClickHouse服務端會對分片數據進行校驗,確保在數據搬遷過程中沒有數據丟失和重複。

 

數據查詢

 

ClickHouse支持SQL查詢(不完全),有HTTP和TCP兩種連接方式,官方和第三方的查詢工具和庫豐富。用戶可以使用命令行,JDBC或者可視化工具快速進行數據查詢的開發和調試。ClickHouse通過MPP(Massively Parallel Processing) + SMP(Symmetric Multiprocessing)充分地利用機器資源,單條查詢語句默認使用機器核數一半的CPU,因此ClickHouse不支持高併發的應用場景。在業務使用層面,最核心的問題是查詢校驗和併發控制,單條過大的查詢或者過高的併發都會導致集羣資源使用率過高,影響集羣穩定性。

 

應用架構

 

 

Ebay Seller Hub通過Reports Service接入ClickHouse查詢,Reports Service提供了Public和Internal兩套API。Internal API提供給Seller Hub以及其他內部的已知應用使用,Public API在eBay Developers Program(詳情見:https://developer.ebay.com/)開放給第三方開發者。

 

 

 

Internal API的查詢直接提交內部線程池執行,線程池的大小根據ClickHouse的集羣機器數量設置。查詢請求執行前會進行校驗,過濾所有非法以及資源不可預估的請求。

 

Public API通過任務提交的方式異步執行查詢,用戶提交的查詢任務存入DB中,Service內部的Schedule定時掃表,根據任務的狀態串行執行查詢任務。執行成功的任務上傳生成Report到文件服務器,用戶拿到URL後自行下載。執行失敗的任務,根據錯誤類型(非法的請求,資源不足等)來選擇是否在下一個週期再次執行。

 

測試發佈

 

 

在生產環境部署完成後,我們開啓了數據雙寫,往ClickHouse裏不斷地插入實時數據和離線數據,直到達到Druid的數據水平。在數據一致性驗證過後,我們鏡像了一份生產服務的查詢,然後把這些查詢轉發給ClickHouse。通過收集和對比Druid和ClickHouse的響應,我們能夠驗證ClickHouse鏈路的數據質量和查詢性能。之後的灰度階段,我們逐漸提升ClickHouse服務生產系統的比例,並保持Druid繼續運行,以保證出現問題可以及時回滾。

 

查詢GUI

 

 

數據可視化方面,我們需要提供類似Turnilo的可視化工具給開發、測試和BI人員使用。ClickHouse支持多種商業和開源的產品接入,我們選用了Cube.JS,並進行了簡單的二次開發。

 

 

總結

 

本文介紹了廣告數據平臺的基本情況,ClickHouse/Druid的特點對比和團隊使用ClickHouse替換Druid的架構方案。ClickHouse表現出了良好的性能和擴展能力,並且還在快速的迭代更新。目前項目已經上線,接下來我們還會和大家繼續分享過程中的碰到的一些問題和解決方法,歡迎大家持續關注。

 

作者丨吳寒思 周路 餘何 來源丨eBay技術薈(I D:eBayTechRecruiting) dbaplus社羣歡迎廣大技術人員投稿,投稿郵箱: [email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章