導讀:過去 3 年時間里,Apache Doris 已經在小米內部得到了廣泛的應用,支持了集團數(shù)據看板、廣告投放/廣告 BI、新零售、用戶行為分析、A/B 實驗平臺、天星數(shù)科、小米有品、用戶畫像、小米造車等小米內部數(shù)十個業(yè)務,并且在小米內部形成了一套以 Apache Doris 為核心的數(shù)據生態(tài) 。本文將為大家分享小米用戶行為分析平臺基于 Apache Doris 向量化版本的改造實踐,包括數(shù)據存儲架構和查詢服務架構的演進與改造經驗分享。
作者|小米數(shù)據智能部開發(fā)工程師 湯佳樹
小米用戶行為分析統(tǒng)一平臺是基于海量數(shù)據的一站式、全場景、多模型、多維度、自助式大數(shù)據智能洞察分析服務平臺,對接各類數(shù)據源,進行加工處理、分析挖掘和可視化展現(xiàn),滿足各類用戶在用戶洞察場景下的數(shù)據分析應用需求,提供高效極致的分析體驗。
業(yè)務需求
平臺可以基于數(shù)據進行時間分析,留存分析,分布分析,漏斗分析等,業(yè)務方主要基于事件進行分析,事件是追蹤或記錄的用戶行為或業(yè)務過程,可以是單個事件也可以是多個事件組合的虛擬事件。
數(shù)據來源于各業(yè)務的打點數(shù)據,且基于事件模型進行建模,用戶在產品中的各種操作都可以抽象成 Event 實體,并且里面都會包含五要素:
Who:即參與這個事件的用戶是誰,例如用戶的唯一 ID
When:即這個事件發(fā)生的實際時間,例如time字段,記錄精確到毫秒的事件發(fā)生時間
Where:即事件發(fā)生的地點,例如根據 IP 解析出的省份和城市
How:即用戶從事這個事件的方式,例如用戶的設備,使用的瀏覽器,使用的 App 版本等等
What:描述用戶所做的這件事件的具體內容,例如點擊類型的事件,需要記錄的字段有點擊 URL,點擊 Title,點擊位置等
數(shù)據基于 OLAP 引擎 Doris 進行存儲,隨著接入業(yè)務不斷增多,且接入的業(yè)務量不斷膨脹,Top 級應用可以達到 100 億條/天,查詢壓力和時間相繼增大,用戶對查詢時延的吐槽愈來愈多,我們急切的需要提升查詢性能來提升用戶的體驗。
痛點問題
針對于業(yè)務需求,我們總結了以下痛點問題:
為了實現(xiàn)復雜的業(yè)務需求,OLAP 分析引擎需要留存、漏斗等分析函數(shù)支撐。
增量數(shù)據?100億/天,導入壓力大,部分業(yè)務要求數(shù)據導入不丟不重。
業(yè)務接入不斷增多,數(shù)據量膨脹,需要 PB 級的數(shù)據下的交互式分析查詢達到秒級響應。
為了解決以上的痛點問題,我們對比了多款 OLAP 分析引擎,最終選擇了 Apache Doris。Doris 提供了留存、漏斗分析等函數(shù),極大程度的簡化了開發(fā)的成本。在數(shù)據導入的過程中,我們嘗試 Doris 剛推出的?Merge On Write Unique Key?導入模型,可以抗住?100 億/天的增量數(shù)據壓力。針對于向量化查詢引擎的改造也是的性能較之前的版本有?3-5 倍的提升。
架構演進
一個優(yōu)秀的系統(tǒng)離不開持續(xù)迭代與演進。為了更好的滿足業(yè)務需求,我們在存儲架構與查詢引擎兩個層面上不斷進行嘗試,小米用戶行為分析系統(tǒng)在上線后,目前已完成 3 次改造,以下將為大家介紹改造歷程。
數(shù)據存儲結構:數(shù)據架構的演進
在小米的用戶行為分析平臺中,原始數(shù)據通過小米自研的消息隊列 Talos,在 Flink 中清洗與建模后,被下游的 Doris 與 Hive 消費。全量的數(shù)據會存儲在 Hive 中,進行批量 ETL 或歷史數(shù)據召回的查詢。實時增量數(shù)據被存儲在 Doris 中,用來做熱數(shù)據的查詢操作。基于冷熱數(shù)據分離的架構,我們進行了 3 次架構的演進。
第一階段:基于明細寬表的查詢
在最初的階段我們使用了基于明細的寬表查詢模式。為了處理靈活多樣的分析請求,在系統(tǒng)中,我們配合統(tǒng)一埋點平臺處理數(shù)據,接入的 OLAP 的數(shù)據是直接埋點的全字段展平。在入庫之前,我們在 Flink 中將數(shù)據打平,以寬表的模式存儲在 Doris 明細表中。根據查詢的需求,我們將經常使用的列作為建表的維度列,利用前綴索引的特性進行查詢加速。但某些頭部大數(shù)據量業(yè)務容易查詢多天數(shù)據,一個大查詢可能就會將集群資源占滿甚至導致集群不可用,且查詢耗時相當之久。
第二階段:基于聚合模型的查詢加速
在改造的第二階段,我們使用了聚合模型對業(yè)務查詢進行加速。?我們對接入行為分析的應用進行統(tǒng)計分析,絕大多數(shù)接入行為分析的應用數(shù)據量在 1 億/天數(shù)據量以內。對于部分使用頻率較高的表,我們采用聚合表完成查詢加速,對單天數(shù)據量超 10 億且高頻的頭部應用做聚合表加速。具體流程為根據數(shù)據量挑選出頭部應用,對其進行字段解析,并挑選出常用指標及維度,由 Hive 表數(shù)據進行聚合 T-1 產出數(shù)據,最后寫入到 Doris 中,進行查詢加速。該階段的改造解決了集群頭部業(yè)務大查詢的問題,此時雖然獨立集群存儲沒問題,但由于其他業(yè)務接入后還會持續(xù)增加數(shù)據量和?埋點字段 ,這樣會導致元數(shù)據最先進入瓶頸。
第三階段(當前階段):業(yè)務適配的建表改造
當前階段,我們對業(yè)務需求進行深度解析后重新規(guī)劃了建表結構。我們對某些應用的埋點字段進行分析,發(fā)現(xiàn)有些用戶埋點字段多達 500+,但在行為分析里實際用到的可能只有 100+,這顯然有所浪費。所以我們與用戶溝通調研需求,配合行為分析平臺側的能力,用戶可在平臺對有用事件和屬性進行篩選,同時設置字段映射和過濾邏輯,然后再進行建表。
查詢服務架構:查詢引擎的改造與演進
我們基于業(yè)務深度改造了查詢的服務架構,構建了新的查詢引擎架構,實現(xiàn) SQL 的權重、路由、緩存和資源調度操作。根據查詢條件,路由引擎會將 SQL 拆分成多條子查詢,在 Doris 或 Hive 中執(zhí)行后,將子查詢的結果匯總,得到最終的結果。針對查詢引擎,我們也進行了 3 次技術架構的改造。
第一階段:基于集群粒度的查詢資源管理
我們對集群粒度進行查詢資源管理,在資源調度中,我們會給每一個 Doris 集群設置一個總的資源池大?。ǜ鶕耗芰蜏y試進行量化),根據數(shù)據量大小和查詢天數(shù)對每個 SQL 進行加權,并對資源池的最大最小并行 SQL 數(shù)進行限制,如果計算的 SQL 超過限制則進行排隊。其次,還會利用 Redis 對數(shù)據進行 SQL 級別緩存。
第二階段:基于 SQL 路由的改造
為適配聚合表加速做了路由層,提升緩存命中率和利用率,此階段拆分原始提交 SQL,基于指標進行緩存,粒度更細,服務端可根據指標進行適當計算更易于緩存命中。值得一提的是排隊時間往往會比較長,有些場景下可能會進行重復提交或拆分成同樣的 SQL,為了提高效率會在 SQL 排隊前和排隊后各進行一次緩存校驗。
第三階段(當前階段):基于 SQL 權重的改造
整體架構方面,由于采取了篩選埋點字段而非全量字段導入 Doris,針對頭部問題用戶,我們會基于查詢歷史統(tǒng)計指標及維度,根據指定的某些規(guī)則進行默認初始化操作,并以此溝通用戶并進行引導升級。此外為了更精細的控制資源調度,本階段對對 SQL 內容進行加權,如含有DISTINCT,LIKE,VARIANCE_SAMP等字樣再加權。對于資源消耗較大的操作,如 DISTINCT,會給予更高的權重,調度引擎在執(zhí)行時會分配更多的資源。
實踐應用
數(shù)據建模
對業(yè)務來講,分析查詢需要較高的靈活度,且是對用戶粒度進行分析,所以需要保留較多的維度和指標,我們選用 Doris 作為存儲查詢引擎,且采用明細表建模,這樣可以保證用戶能夠根據分析需求查出數(shù)據。另一方面,由于查詢分析是一個延時要求較高的產品,對于數(shù)據量大、查詢天數(shù)多、語句復雜的情況,查詢延時會很高,所以對于頭部應用,我們根據高頻指標維度進行了聚合表模型建模。
CREATETABLE`doris_XXX_event`(`olap_date`bigint(20)NOTNULLCOMMENT"",`event_name`varchar(256)NOTNULLCOMMENT"",`uniq_id`varchar(256)NOTNULLCOMMENT"",`dim1`varchar(256)REPLACENULLCOMMENT"",`dim2`varchar(256)REPLACENULLCOMMENT"",? ...`cnt`bigint(20)REPLACENULLCOMMENT"",`index1`doubleREPLACENULLCOMMENT"",`index2`doubleREPLACENULLCOMMENT"",? ...) ENGINE=OLAPAGGREGATEKEY(`olap_date`,`event_name`,`uniq_id`)COMMENT"OLAP"PARTITIONBYRANGE(`olap_date`)
數(shù)據導入
明細表部分,我們接入 Json 格式 TalosTopic,動態(tài)獲取 Doris 表的 Schema 信息,通過雙緩沖區(qū)循環(huán)攢批的方式,利用 StreamLoad 向 Doris 中寫數(shù)據,如果在導入 Doris 時有出現(xiàn)失敗的批次,重試 10 次仍然失敗,會將數(shù)據按照應用粒度存入 HDFS,并在凌晨定時調度任務重新寫入 T-1 未寫入的數(shù)據。聚合表部分,我們由 Talos 落盤的 Iceberg 表,每日進行 T-1 數(shù)據的聚合,根據服務端選取的維度和指標,以及聚合類型(count?,count distinct?,?sum?,max?,min ),進行聚合存入中間 Hive 表,再由統(tǒng)一導入 Doris 程序進行導入。
數(shù)據管理
明細數(shù)據和應用聚合表分庫存儲,TTL 均為 33 天。數(shù)據表會有數(shù)據質量監(jiān)控,如果總行數(shù)或者設置指標環(huán)比波動太大,會進行告警人工介入確認數(shù)據是否有誤,視緊急程度進行回補處理。
數(shù)據查詢及應用
絕大多數(shù)用戶會錨定事件,進行含指標聚合,去重用戶數(shù)(幾乎占總查詢的 50%)的事件行為分析,同時還會有留存分析,漏斗分析,分布分析等分析類型。
建表模型的維護
為了適配業(yè)務的變更,上游的埋點信息會周期性的更新。原有的表結構需要進行變更以適配埋點的增加。在過去的 Doris 版本中,Schema Change 是一項相對消耗較大的工作,需要對文件進行修改。在新版本中開啟 Light Schema Change 功能后?,?對于增減列的操作不需要修改文件,只需要修改 FE 中的元數(shù)據,從而實現(xiàn)毫秒級的 Schame Change 操作。
應用現(xiàn)狀
小米目前在?300?多個業(yè)務線上線了 Doris 集群,超過?1.5PB?的業(yè)務數(shù)據。在初期我們選擇了兩個使用較為頻繁的集群進行向量化升級。
現(xiàn)遷移 Doris 向量化集群的行為分析業(yè)務有 2 個,7 天增量數(shù)據的平均值在百億左右,存儲空間占用?7T/天左右。在升級到向量化的版本后,存儲資源有較大的節(jié)省,只需要原有集群約 2/3 的存儲空間。
性能提升
請求粒度
升級 Doris 向量化版本后,行為分析平臺以請求粒度統(tǒng)計查詢耗時 P80 和均值,P80 耗時下降 43%?,平均耗時下降 27%?;統(tǒng)計口徑:匯總 12.07-12.11 期間,行為分析請求粒度查詢執(zhí)行時間。
SQL 粒度
升級 Doris 向量化版本后,行為分析平臺以?SQL 粒度來統(tǒng)計查詢耗時 P80 和均值,耗時 P80?下降 70%?,平均耗時下降 54%?。統(tǒng)計口徑:匯總 12.04-12.11 期間,行為分析 SQL 粒度查詢執(zhí)行時間(未含排隊)
升級 Doris 向量化版本后,行為分析平臺以?SQL 粒度統(tǒng)計查詢耗時 P80 和均值,耗時 P80?下降 56%?,平均耗時下降 44%?;
統(tǒng)計口徑:匯總 12.02-12.11,行為分析 SQL 粒度查詢總時間?(含排隊)
去重優(yōu)化
在 ID-Mapping 的時候,通常需要針對 ID 進行去重操作。在最初我們使用了COUNT DISTINCT來完成去重。
SELECTa.`olap_date`AS`time`,count(distincta.`distinct_id`)ASdistinct_idFROManalysis.doris_XXX_event aWHERE`a`.`olap_date`BETWEEN20221218AND20221220ANDa.`event_name`IN(XXXX, XXX, XXX, XXX)AND... ...GROUPBY1ORDERBY2DESCLIMIT10000
在經過優(yōu)化后,我們使用子查詢+ GROUP BY來替代COUNT DISTINCT的功能
SELECTz.`time`,count(distinct_id) var1FROM(SELECTa.`olap_date`AS`time`,? ? ? ? ? ? ? ? ? ? ? ?? a.`distinct_id`ASdistinct_idFROManalysis.doris_XXX_event aWHERE`a`.`olap_date`BETWEEN20221218AND20221220ANDa.`event_name`(XXXX, XXX, XXX, XXX)AND... ...GROUPBY1,2) zGROUPBY1ORDERBY2DESCLIMIT10000
相較于原有的COUNT DISTINCT,使用子查詢+ GROUP BY?的模式性能有?1/3 的提升。
未來規(guī)劃
在過去的三年時間里,Apache Doris 已經在小米內部得到了廣泛的應用,支持了集團數(shù)據看板、廣告投放/廣告 BI、新零售、用戶行為分析、A/B 實驗平臺、天星數(shù)科、小米有品、用戶畫像、小米造車等小米內部數(shù)十個業(yè)務,并且在小米內部形成了一套以 Apache Doris 為核心的數(shù)據生態(tài) 。隨著業(yè)務的持續(xù)增長,未來我們會進一步推動小米的其他業(yè)務上線向量化版本。
非常感謝 Apache Doris 社區(qū)與 SelectDB 公司的鼎力支持,小米集團作為 Apache Doris 最早期的用戶之一,一直深度參與社區(qū)建設,參與 Apache Doris 的穩(wěn)定性打磨,未來我們也會密切聯(lián)系社區(qū),為社區(qū)貢獻更多的力量。