1、概述
WeLab是業內領先的金融科技公司。我們以定製化服務的方式為合作夥伴提供金融智能解決方案,幫助合作夥伴實現金融科技創新。WeLab擁有獨創的風險管理技術,可以高效地整合和分析移動端大數據,並對用戶的風險進行定級,高效地輸出決策。為了實現秒級決策,我們對數據處理的實時性,準確性和安全性都有很高的要求。Apache Doris資料庫就是在這樣的背景下被引入到我們大數據平臺中來的,並最終成為了我們大數據平臺的重要基石之一。
WeLab的實時大數據平臺是一套包含了數據實時採集、存儲、集成、挖掘、分析和可視化的綜合性大數據平臺。它具有管理自動化、流程化、規範化、智能化等特點,並能夠支撐更輕量、靈活、低門檻並快速迭代的大數據應用。
在這個大數據平臺體系中,Apache Doris主要支撐了兩個重要的場景:實時自助BI報表和用戶運營分析。
2、實時自助BI報表
在大數據平臺建設初期,我們完全依賴Hadoop技術生態,利用離線計算提供分析服務。但是Hadoop技術棧對實時性支持得不夠好,而且基於Hadoop技術棧開發報表成本比較高,不夠靈活。
另一方面,在這個時期,報表的輸出都是以傳統BI的模式提供的,但是傳統BI部署開發周期較長,需進行整體的架構設計,各個模塊均需要進行技術開發。在這種模式下,新需求的開發也非常耗時,IT部門負擔較重。從這種大數據分析輸出的效果來看,運營人員無法實時地通過數據來分析用戶的行為路徑,也就無法迅速地在產品,業務上做出相應的對策。
為了解決上述兩個問題,我們一方面希望引入能夠進行實時數據分析的技術方案,另一方面希望能用自助BI來替代傳統BI。自助BI比傳統BI更加的靈活且易於使用,非IT背景的業務分析人員也可以方便使用,可以更好地滿足用戶的數據分析需求。
我們的升級工作從調研市面上的各種MPP執行引擎開始。我們一共調研了Kudu+Impala,Greenplum和Apache Doris三種MPP執行引擎,具體結果如下。
經過全面的對比分析,我們最終放棄了Kudu+Impala和Greenplum,決定使用Doris來作為實時大數據平臺的底層存儲。
2.1 數據表設計
利用Doris的多種數據模型,我們的事件表和維度表設計方案如下。
事件表: Duplicate 模型。Duplicate模型沒有主鍵,可根據指定欄位,數據可重複。
Bitmap_uv表:Aggregate 模型。聚合模型需指定聚合欄位。
維度表: Uniq 模型。設定key,具有唯一性。可進行覆蓋數據操作。
以上這個設計是非常簡單的,有別於傳統數倉中多層級表的設計理念。通過這樣的輕便設計,一旦業務方有分析需求,只需在數據總線的界面操作配置好,把業務方的表數據同步到doris中。然後通過自助分析就可以輕鬆得到報表的相關結果。
2.2 建表和查詢
以下是一個事件表的建表例子。
通過自助BI界面,只需要進行拖拉拽,就能轉化成底層SQL。以下是一個通過自助BI生成的底層SQL例子。
2.3 實踐經驗
在基於Doris構建上述實時報表的過程中,我們總結了一些Doris的使用經驗。
1. 分區與分桶。Doris中,通過關鍵字Partitiion進行分區,通過關鍵字Distributed進行分桶。分區分桶的關鍵字都必須先定義在建表模型的key裡面。分區分桶很好地優化了大表查詢性能。不過選擇什麼欄位作為分區分桶欄位是需要考慮的。假如在一個sql中,條件裡如果沒有命中分區欄位,分桶欄位,那麼查詢性可能會大打折扣的。再提一點的是,Doris很好地支持了動態分區功能,這對於開發人員來說是非常友好的。而Kudu的分區只能手動的。
2. 前綴索引。上文的建表腳本最前面的欄位是event_name,event_time,user_id。那是因為這幾個欄位都是經常作為查詢的條件欄位,這樣的建表方式有利於前綴索引發揮作用。在 Aggregate、Uniq 和 Duplicate 三種數據模型中。底層的數據存儲,是按照各自建表語句中,AGGREGATE KEY、UNIQ KEY 和DUPLICATE KEY 中指定的列進行排序存儲的。
3. 並發數。如果在實踐中發現SQL查詢性能不佳,並且觀察到機器的cpu利用率不高,可以嘗試調節分桶數,並發數。並發數 = (分桶數 * 分區數) / 機器數,相應地設置「parallel_fragment_exec_instance_num」這個參數。
4. Colocate Join。Doris支持多種分布式Join的方式,不僅支持Broadcast Join、Shuffle Join,還支持Colocate Join。相比 Shuffle Join 和 Broadcast Join,Colocate Join 在查詢時沒有數據的網絡傳輸,性能會更高。在 Doris 的具體實現中,Colocate Join 相比 Shuffle Join 可以擁有更高的並發粒度,也可以顯著提升 Join 的性能。詳情可參考(https://blog.bcmeng.com/post/doris-colocate-join.html#why-colocate-join)。
2.4 性能測試
以下是我們結合自身的場景對Doris進行性能測試的結果。
1. 創建事件表5000W,用戶表4000W進行關聯查詢
2. 調整參數,tc_use_memory_min=21474836480,chunk_reserved_bytes_limit=21474836480,移除sql 的order by
3. Collocate Join
4. 提升機器配置,8C->16C
以上的驗證,分別通過改變sql語法,調整相關參數,使用Collocate Join,匹配前綴索引,甚至提升機器配置的方式提升了sql查詢的性能。後面的測試都是在並發導入的同時對查詢進行壓測。從測試結果看,Doris引擎的查詢能力是非常優秀的。
2.5 報表展示
基於Doris優秀的查詢能力,我們自助BI系統建設變得非常容易。下圖是WeLab最終實現的自助BI分析系統的截圖。通過這個分析系統,業務人員只需要幾分鐘,就可以看到出他們想要的數據分析結果。不論是從開發成本,維護成本,還是快速分析帶來的業務收益來看,實時自助BI報表對業務的價值都是十分顯著的。
3 在線用戶運營
眾所周知,獲客成本高是當今困擾各類網際網路金融APP的一個重大問題。目前應對該問題的最好方法是對用戶行為進行有效的分析,探索不同用戶的關鍵行為,洞察指標背後的增長點。並通過事件、留存、漏鬥、用戶畫像等相關模型追蹤用戶行為,用數據指引產品改進方向,並快速驗證。
在用戶行為分析中,以用戶行為轉化模型(如:漏鬥,留存率等)的建立和計算最為關鍵,也最為複雜。WeLab實時大數據平臺在計算用戶行為轉化模型上,經歷過幾個階段:離線計算階段、Hbase階段和目前的Doris階段。
3.1 離線計算階段
上文已經提到,在大數據平臺建設初期,我們是完全通過Hadoop大數據技術的生態來進行用戶行為模型的計算的。當時我們把數據存放在HDFS上,然後通過MR來計算用戶行為的轉化結果,以此實現漏鬥,留存等轉化模型。
這種方式的最大問題是時效性很差,一般都是「T+1」的交付方式,對於運營人員來說,他們無法快速觀察用戶使用產品的情況,也就降低了對產品優化的效率。
3.2 Hbase階段
為了增加用戶行為轉化的時效性,我們參考了大量的資料,其中包括美團分享的《每天數百億用戶行為數據,美團點評怎麼實現秒級轉化分析?》(https://tech.meituan.com/2018/03/20/user-funnel-analysis-design-build.html)。通過對各種案例的調研,我們發現使用bitmap計算用戶轉化相關的分析模型是比較好的方案。但當時我們沒有調研到有支持bitmap結構的大數據存儲,所以我們基於hbase,通過它獨有的結構,構造出一個偽bitmap的數據結構。
這種方式需要對Hbase的Rowkey進行特殊處理,需要用表名、欄位、值、時間4個要素組合形成Rowkey,再通過序列變為字節存放。這樣便可以對任意維度定義為標籤,把用戶ID作為column來存放。界面可以實現隨意選擇欄位,值作為條件過濾用戶。但hbase本身不支持bitmap的交集運算,所以必須把數據先加載到java內存,轉換為RoaringLongBitmap模型,最後才可以進行各種用戶轉換的計算。
但這種方式在後期遇到了很大的性能問題。隨著Scan Rowkey量的變大,value創建的column也會變得越來越多,最後必須通過優化column數目來優化性能。每次查詢時,都需要把大量數據先加載到內存後進行bit運算,非常消耗內存資源。
3.3 Doris階段
為了解決Hbse方案的性能問題,我們繼續調研支持Bitmap數據結構的開源大數據存儲系統。非常巧的是,在我們尋找新的MPP執行引擎的同時,發現了Apache Doris 是支持bitmap結構的。通過調研,並參考了美團工程師分享文章《Apache Doris 基於 Bitmap的精確去重和用戶行為分析》(https://blog.bcmeng.com/post/doris-bitmap.html#a-store-about-bitmap-count-distinct)中的設計思路,我們對平臺的用戶轉化分析功能進行了重構。
具體來說,我們的工作分為:建表,數據導入、數據格式轉換、SQL查詢幾個步驟。
3.3.1 建表
我們的表結構參考了Hbase Rowkey的設計,保留了表、欄位、值、時間等主要要素。建表腳本如下:
3.3.2 數據導入
Doris支持多種數據導入方式(具體可以參考Doris的官方文檔),在我們的場景中,我們採用的是Stream Load的方式。因為我們數據倉庫的設計是先由上遊各個業務層的數據存儲,包括關係型資料庫、日誌、MQ等多種數據來源,統一訂閱到數據總線,經過加工、清洗,再由數據工坊寫入到指定的大數據存儲。Stream Load的原理是通過http的方式導入數據,這樣可以很好地適配到數據工坊統一寫入存儲的接口。
Stream Load的性能是非常卓越的,符合我們大數據平臺所需要的實時性要求。以下是我們對Doris做的應用層導入性能測試結果。
從測試的結果可以看出,Stream Load的導入性能受到幾方面因素的影響,包括每次導入的數據量、導入任務的並發數、機器配置等。為了把導入性能發揮到極致,必須要結合實際情況對這幾方面因素進行必要的調整。
不過,對於我們平臺而言,把數據緩存到內存,再調用Stream Load的方式會有一些缺點。例如,數據會先積攢在java內存,再寫入到Doris。那麼當任務數越來越多,批次越來越大,整體消耗的內存會越來越大,可能會導致OOM。所以建議在線上使用之前,先模擬一個生產環境的數據體量,進行性能測試,得出性能指標作為參考。
3.3.3 數據轉換
導入的數據是按行存儲的,例如,事件表的一行數據裡,包含了用戶的名稱、國家、年齡、性別等欄位,這些欄位對應值都可以成為一個標籤。在數據轉換時需要將每行數據中的不同列,轉換成對應bitmap結構中的信息,然後再導入對應的Doris表中。
3.3.4 SQL查詢
最後,通過sql查詢就可以實現在數據存儲底層完成bitmap的交集運算。以下是我們進行交集運算的一個例子。
Doris引擎的bitmap查詢性能優越,基本都是秒級出結果。在功能方面,bitmap還有可以加強的地方。例如,在bitmap的查詢API中沒有可以按列表形式返回bitmap中用戶ID的方法。只有一個「BITMAP_FROM_STRING」方法,可以把bitmap轉換為字符串形式。但字符串是不能直接通過sql查詢返回的,因為有可能bitmap的用戶數量非常的龐大,可能有上千萬甚至上億的數量級。如果以列表的形式,則可以通過分頁截取用戶ID列表大小,然後反查用戶明細到前端展示,有利於運營追蹤用戶詳情。
4 總結
本文講述了WeLab實時大數據平臺是如何整合Apache Doris引擎,以及我們是如何思考和處理在平臺搭建中遇到的一些問題的。
在平臺的不斷演進中,我們意識到,Hadoop生態固然是大數據技術的基石。但隨著技術的發展,hadoop生態的開發成本,運維成本,很難滿足現今網際網路日新月異的業務快速迭代需求。其實並不是所有公司都適合hadoop這種龐大的大數據生態。
MPP引擎代表了大數據未來發展的一種趨勢。其中Apache Doris是MPP引擎的優秀代表。MPP架構的最原始想法是消除共享資源,每個執行器有單獨的CPU,內存和硬碟資源。一個執行器無法直接訪問另一個執行器上的資源,除非通過網絡上的受控的數據交換。這種架構較完美地解決了可擴展性的問題。
但無論是哪種技術都不是完美的,任何技術必須不斷進步,不斷發展,才能更好地滿足用戶的需求,才能真正體現技術的價值。希望各位技術人一起努力,繼續推進偉大的技術發展。
作者:黃文威,WeLab架構工程師