天天看點

從 Clickhouse 到 Apache Doris,慧策電商 SaaS 高并發資料服務的實踐

作者:SelectDB

作者介紹: 馬成,慧策 JAVA進階研發工程師

慧策(原旺店通)是一家技術驅動型智能零售服務商,基于雲計算 PaaS、SaaS 模式,以一體化智能零售解決方案,幫助零售企業數字化智能化更新,實作企業規模化發展。憑借技術、産品、服務優勢,慧策現已成為行業影響力品牌并被零售企業廣泛認可。2021年7月,慧策完成最新一輪 D 輪 3.12 億美元的融資,累計完成四輪逾 4.52 億美元的融資,與諸多國際一流企業、行業頭部企業并列而行,被全球頂尖投資公司看好。

業務需求

慧經營是一款資料分析産品,主要提供經營分析、營運分析、應收對賬三大功能,面向企業的經營、營運、财務三個角色。如圖所示,慧經營上遊為常見的電商平台、直播平台以及慧策主要的産品旺店通,這些平台在交易過程中會産生大量的資料,包括收入、成本以及多種費用相關的資料。這些資料都比較分散,如果客戶手動進行資料彙總和分析,過程繁瑣、難度較高且展示不夠直覺。而慧經營可以在客戶授權下擷取、彙總這些資料,根據客戶需求提供經營分析、報表生成、賬單彙總等多項資料分析服務,以幫助客戶更好地經營店鋪。

從 Clickhouse 到 Apache Doris,慧策電商 SaaS 高并發資料服務的實踐

為了能承載上述資料相關的服務,我們在系統架構設計之初需要考慮以下幾點:

  • 低成本:慧經營的付費模式為按需付費,這要求架構必須具有輕量化、易維護的特性。基于這點考慮,首先排除基于 Hadoop 的生态架構,雖然 Hadoop 足夠成熟,但是元件依賴度較高、繁瑣複雜,無論是運維成本還是使用成本都非常高。
  • 高性能:電商資料為慧經營的主要資料來源,資料次元豐富, ETL 複雜度高;另外,在很多使用場景中明細查詢與聚合查詢是并存的,既需要夠快速定位資料範圍,又需要高效的計算能力,是以需要一個強大的 OLAP 引擎來支撐。
  • 合理資源配置設定:客戶規模差異較大,有月單量隻有 1 萬的小客戶,也有月單量高達千萬級别的大客戶,資源合理配置設定在這樣的場景下異常重要,是以要求 OLAP 引擎可以在不影響使用者體驗的前提下,可以根據客戶的需求進行資源配置設定,避免大小查詢資源搶占帶來的性能問題。
  • 高并發:能夠承受上遊平台多來源、高并發的大量資料的複雜 ETL,尤其在 618、雙 11 這樣的業務高峰期,需要具備高效查詢能力的同時,能夠承擔大量的寫入負載。

架構演進

架構 1.0

從 Clickhouse 到 Apache Doris,慧策電商 SaaS 高并發資料服務的實踐

基于以上考慮,我們在架構 1.0 中引入 Clickhouse 作為 OLAP 引擎。從上圖可看出該架構是一個完全基于後端 Java 以及 Spring 的技術架構,通過 Binlog 同步的方式通過 Canal 和 Kafka 将資料從 MySQL 同步至Clickhouse,來承接前端的各種經營分析報表服務。

架構 1.0 在上線不久後就遭遇了慢查詢問題。在早期客戶和資料量較少時,查詢性能尚可滿足客戶需求,但是随着資料量的不斷增大,受限于 MySQL 本身的特性, ETL 效率逐漸低到無法令人接受,尤其在面對大客戶場景時,即使命中索引、掃描資料範圍僅在百萬級别,MySQL 應對該場景也已十分吃力。其次,面對激增的資料,ClikHouse 的多表 Join 也遭遇性能問題,由于其幾乎不支援分布式 Join,盡管提供了 Join 語義、但在使用上對多表 Join 的支撐較弱、複雜的關聯查詢常常會引起 OOM。

在 ClickHouse 單機性能不能支撐業務時,我們考慮擴充搭建叢集以提高性能,而 ClickHouse 分布式場景需要依賴 Zookeeper,同時需要單獨維護一套分布式表,這将使運維管理的難度和成本不斷升高。

除此之外,ClickHouse 還有幾個較大的問題,背離了我們最初對架構的選型要求:

  • 不支援高并發,即使一個查詢也會用伺服器一半的 CPU。對于三副本的叢集,通常會将 QPS 控制在 100 以下。
  • ClickHouse 的擴容縮容複雜且繁瑣,目前做不到自動線上操作,需要自研工具支援。
  • ClickHouse 的 ReplacingMergeTree 模型必須添加final 關鍵字才能保證嚴格的唯一性,而設定為final後性能會急劇下降。

架構 2.0

我們在架構 2.0 中引入 Apache Doris 作為 OLAP 引擎,并進行了一次整體的架構更新。選擇 Apache Doris 的主要原因有如下幾條:

  • 使用成本低: 隻有 FE 和 BE 兩類程序,部署簡單,支援彈性擴縮容,不依賴其他元件,運維成本非常低;同時相容 MySQL協定 和标準 SQL,開發人員學習難度小,項目整體遷移使用成本也比較低。
  • Join 性能優異: 項目存在很多曆史慢 SQL ,均為多張大表 Join,Apache Doris 良好的 Join 性能給我們提供了一段優化改造的緩沖期。
  • 社群活躍度高: 社群技術氛圍濃厚,且 SelectDB 針對社群有專職的技術支援團隊,在使用過程中遇到問題均能快速得到響應解決。
從 Clickhouse 到 Apache Doris,慧策電商 SaaS 高并發資料服務的實踐

如上圖所示,我們将原本基于 MySQL 的基礎資料存儲遷移到 Doris 中,同時将大部分的 ETL 遷移至在 Doris 内部進行,MySQL 隻用于存儲配置資訊。同時引入了 Flink,DolphinScheduler 等元件,成功建構了一套以 Doris 為核心、架構簡潔、運維簡單的資料生産體系。

全新的架構也給我們帶來的顯著的收益:

  • ETL 效率極大提升:慧經營的資料次元豐富、 ETL 複雜度高,得益于 Apache Doris 強大的運算能力及豐富的資料模型,将 ETL 過程放在 Doris 内部進行後效率得到顯著提升;
  • Join 耗時大幅降低:查詢性能同樣得到極大提升,在 SQL 未經過改造的情況下,多表 Join 查詢耗時相較于過去有了大幅降低。
  • 并發表現出色:在業務查詢高峰期可達數千 QPS,而 Apache Doris 面對高并發查詢時始終表現平穩;
  • 存儲空間節省:Apache Doris 的列式存儲引擎實作了最高 1:10 的資料壓縮率,使得存儲成本得到有效降低。
  • 運維便捷:Apache Doris 架構簡單、運維成本低,擴容更新也非常友善,我們前後對 Doris 進行了 3 次更新擴容,基本都在很短的時間内完成。

在使用 Apache Doris 的過程中,我們對 Doris 如何更好地應用也進行了探索,在此期間總結出許多實踐經驗,通過本文分享給大家。

實踐應用

分區分桶優化

在執行 SQL 時,SQL 的資源占用和分區分桶的大小有着密切的關系,合理的分區分桶将有效提升資源的使用率,同時避免因資源搶占帶來的性能下降。

是以我們在建立事實表分區時,會根據客戶的資料規模提供相比對的分區方案,比如資料規模較小按年分區、規模大按月分區。在這種分區方式下,可以有效避免小查詢占用過多資源問題,而大客戶的使用體驗也由于細粒度的分區方式得到了提升。

CREATE TABLE DWD_ORDER_... (    
...)    
...
PARTITION BY RANGE(tenant,business_date)
(
PARTITION p1_2022_01_01 VALUES [("1", '2022- 01- 01'), ("1", '2023- 01- 01')),
PARTITION p2_2022_01_01 VALUES [("2", '2022- 01- 01'), ("2", '2022- 07- 01')),
PARTITION p3_2022_01_01 VALUES [("3", '2022- 01- 01'), ("3", '2022- 04- 01')),
PARTITION p4_2022_01_01 VALUES [("4", '2022- 01- 01'), ("4", '2022- 02- 01')),    
...
)
           

而分桶的設定上我們采用了最新版本中增加的自動分桶推算功能,使用方式非常便捷,不用再去測算和預估每張表的資料量以及對應 Tablet 的增長關系,系統自動幫助我們推算出合理分桶數,提升性能的同時也使得系統資源得到更好利用。

參考文章:一文教你玩轉 Apache Doris 分區分桶新功能|新版本揭秘

多租戶和資源隔離方案

在 SaaS 業務場景中,多租戶和資源劃分是架構設計過程中必不可少的部分。多租戶(Multi-Tenancy )指的是單個叢集可以為多個不同租戶提供服務,并且仍可確定各租戶間資料隔離性。通過多租戶可以保證系統共性的部分被共享,個性的部分被單獨隔離。

對于我們來說,客戶規模差異較大,有月單量隻有 1 萬的小客戶,也有月單量高達千萬級别的大客戶,資源的合理配置設定與隔離在這樣的場景下異常重要。如果為每個租戶建立一個資料庫叢集,則叢集規模不可控且造成資源浪費。如果多個租戶共享一套資料庫叢集,使用者的需求可以互相補償,總體來時可以有很大的資源節約,并且計算規模越大成本越低,而在應對客戶查詢時,可以根據客戶的資料規模和查詢需求将資源池劃分給各客戶。

這裡我們采用了 Apache Doris 的節點資源組來區分大小客戶,避免了不同租戶以及查詢間的資源搶占問題。

節點資源組劃分

節點資源劃分指将一個 Doris 叢集内的 BE 節點設定标簽(Tag),标簽相同的 BE 節點組成一個資源組(Resource Group),資源組可以看作是資料存儲和計算的一個管理單元。資料入庫的時候按照資源組配置将資料的副本寫入到不同的資源組中,查詢的時候按照資源組的劃分使用對應資源組上的計算資源對資料進行計算。

從 Clickhouse 到 Apache Doris,慧策電商 SaaS 高并發資料服務的實踐

例如我們将一個叢集中的 3 個 BE 節點劃分為 2 個資源組,分别為資源組 A 和資源組 B,BE-1 和 BE-2 屬于資源組A,BE-3 屬于資源組B。資源組 A 有 2 副本的資料,資源組 B 有一個副本的資料。那麼當客戶 A 在寫入資料和查詢資料的時候會按照資源組配置使用資源組 A 上的存儲和計算資源,當客戶 B 寫入資料和查詢資料的時候會按照資源組配置使用資源組 B上 的存儲和計算資源。這樣便能能很好的實作同一個叢集,為不同租戶提供不同的負載能力。

具體操作如下:

  1. 設定标簽:

為 BE 節點設定标簽。假設目前 Doris 叢集有 3 個 BE 節點。分别為 host[1-3]。在初始情況下,所有節點都屬于一個預設資源組(Default)。

我們可以使用以下指令将這6個節點劃分成3個資源組:group_a、group_b:

alter system modify backend "host1:9050" set ("tag.location" = "group_a");
  alter system modify backend "host2:9050" set ("tag.location" = "group_a");
  alter system modify backend "host3:9050" set ("tag.location" = "group_b");
           

這裡我們将 host[1-2] 組成資源組 group_a,host[3] 組成資源組 group_b。

  1. 設定資源組資料配置設定政策

副本分布政策定義:資源組劃分好後,我們可以将客戶資料的不同副本分布在不同資源組内。假設一張使用者表 UserTable。我們希望資源組 A 記憶體放 2 個副本,資源組 B 存放 1 分副本

create table UserTable (k1 int, k2 int)
  distributed by hash(k1) buckets 1
  properties(
      "replication_allocation"="tag.location.group_a:2, tag.location.group_b:1"
  )
           

資源組綁定:通過設定客戶的資源組使用權限,來限制某一客戶的資料導入和查詢隻能使用指定資源組中的節點來執行。

set property for 'user_a' 'resource_tags.location' = 'group_a';
  set property for 'user_b' 'resource_tags.location' = 'group_b';
           

這裡将 user_a 和 group_a 資源綁定,user_b 和 group_b 資源綁定。綁定完成後,user_a 在發起對 UserTable 表的查詢時,隻會通路 group_a 資源組内節點上的資料副本,并且查詢僅會使用 group_a 資源組内的節點計算資源。

通過 Apache Doris 提供多租戶和資源隔離方案,能夠将叢集資源更合理的配置設定給各 客戶 ,可以讓多租戶在同一 Doris 叢集内進行資料操作時,減少互相之間的幹擾,同時達到資源成本的有效降低。

高并發場景的支援

高并發也通常是 SaaS 服務場景面臨的挑戰,一方面是慧經營已經為衆多客戶提供了分析服務,需要去同時承載大規模客戶的并發查詢和通路,另一方面,在每日早晚業務高峰期也會面臨更多客戶的同時線上,通常 QPS 最高可達數千,而這也是 Apache Doris 表現得非常出色的地方。在上遊 Flink 高頻寫入的同時,Apache Doris 表現極為平穩,随着查詢并發的提升,查詢耗時相較于平時幾乎沒有太大的波動。

應對高并發場景的關鍵在于利用好分區分桶裁剪、索引、緩存等系統機制來減少底層資料掃描。在 Doris 中會将資料表的前幾列作為排序鍵來建構字首索引,同時還有 ZoneMap 以及 Bloom Filter 等索引。在執行查詢時,通過分區分桶裁剪以及索引可以快速過濾到不在查詢範圍内的資料,減少 CPU 和 IO 的壓力。

在與社群的溝通中還了解到,即将釋出的新版本還将進一步提升并發支援,引入行存儲格式、短路徑優化以及預處理語句等來實作上萬 QPS 的超高并發,可以滿足更高并發要求的 Data Serving 場景,這也是我們十分期待的功能。

資料生命周期管理

從 Clickhouse 到 Apache Doris,慧策電商 SaaS 高并發資料服務的實踐

我們自研了一套生命周期管理工具,基于資源的配置設定,可以提供客戶級定制化冷卻政策。根據各個業務場景的客戶需求及付費情況,提供不同長度的資料保留政策,同時得益于 Apache Doris 提供的 OutFile 功能,實作删除或者導出 S3 兩種冷卻方式,當我們再次需要這些資料時,可通過 Load 的方式從 S3 導回資料。

除了通過 OutFile 将資料檔案導出至 S3 以外,社群在後續版本中還将提供分區級别的冷熱資料分離政策。目前我們資料分區都是基于日期範圍來設定,是以可以利用時間分區進行冷熱資料的劃分。通過配置分區級别的 Freeze Time,轉冷後的曆史資料可以自動下沉至成本更低的對象存儲上。在面對曆史冷資料的查詢時,Doris 會自動拉取對象存儲上的資料并在本地 Cache 以加速查詢,而無需執行導入操作。通過冷熱資料分離以及冷資料 Cache,既能保證最大程度的資源節省,也能保證冷資料的查詢性能不受影響。

總結規劃

收益

引入 Apache Doris 之後,新架構的整體查詢響應速度都有了較大的提升, 存儲成本顯著降低,後續我們将繼續探索 Doris 新特性,進一步實作降本增效。

規劃

  • 目前正在強化 Apache Doris 的中繼資料管理建設,我們希望通過該服務能更好的協助開發人員使用 Doris,包括資料血緣追蹤等;
  • 嘗試使用更多 Apache Doris 的新功能,在 1.2.0 版本中新增的 Java UDF 功能可以極大降低資料出入庫的頻率,更便捷地在 Doris 内部進行資料 ETL,這一功能我們正在嘗試使用中;
  • 探索更好的資源配置設定方案,包括 SQL 代理以及嘗試 Doris 後續提供的 Spill 功能,以更好進行資源配置設定應用。

最後,再次感謝 Apache Doris 社群和 SelectDB 技術團隊在我們使用過程中提供的許多指導和幫助,提出問題都會及時的響應并盡快協助解決,未來我們也希望深度參與到社群建設中,為社群的發展出一份力。