ClickHouse在京東小程序自定義數(shù)據(jù)分析中的應用與實踐
一、 業(yè)務背景
隨著移動互聯(lián)網(wǎng)的快速發(fā)展,小程序作為當下零售環(huán)境下的嶄新載體,它憑借著入口豐富、場景多元、傳播能力強、觸手可及以及用完即走的特點,得到了廣泛的認可和傳播。而在小程序的日常運營與發(fā)展中,存在著多樣的數(shù)據(jù)信息,面對如此豐富的數(shù)據(jù)生產(chǎn)資料,如何高效靈活地對這些原始數(shù)據(jù)進行分析與挖掘,迅速掌握小程序數(shù)據(jù)的波動,洞察小程序用戶行為變化,是目前國內(nèi)各個小程序平臺不斷追求突破的問題。因為只有不斷提高數(shù)據(jù)的分析效率,才能更好地沉淀數(shù)據(jù)分析的能力,進而借助于數(shù)據(jù)的深層潛在價值為小程序的業(yè)務發(fā)展而賦能。
京東小程序數(shù)據(jù)中心已涵蓋用戶行為分析、留存分析、用戶畫像及來源分析等四大基礎數(shù)據(jù)分析模塊,涉及的數(shù)據(jù)指標多達60+。
早期的數(shù)據(jù)主要由京東小程序客戶端引擎SDK進行采集,通過子午線原生渠道進行統(tǒng)一上報,再由服務端統(tǒng)一清洗處理;這種模式雖然可以覆蓋大部分基礎數(shù)據(jù)分析的場景,但是仍然存在如下痛點問題:
1、數(shù)據(jù)類型不完整:基礎數(shù)據(jù)指標僅為小程序框架可以獲取的數(shù)據(jù),而小程序內(nèi)開發(fā)者自有代碼的頁面曝光、點擊等業(yè)務數(shù)據(jù),小程序框架無法自動獲取,導致小程序數(shù)據(jù)平臺提供數(shù)據(jù)的完整性無法得到保證。例如,針對ISV商家開發(fā)的某營銷類小程序,我們無法采集并分析到該小程序在進行營銷活動時,某一個領券按鈕的用戶點擊數(shù)據(jù)。
2、行業(yè)數(shù)據(jù)無法沉淀:小程序涵蓋的業(yè)務場景豐富多樣,且復雜程度不一,早期的數(shù)據(jù)中心,僅提供后置的數(shù)據(jù)分析展示,因為業(yè)務數(shù)據(jù)缺失,無法提供基于行業(yè)的預測分析模型,很難為商家提供更為有效的經(jīng)營指導策略支持。
3、無法滿足多變的數(shù)據(jù)統(tǒng)計需要:目前已有的數(shù)據(jù)分析是固化的、預置的且不可變的,自定義數(shù)據(jù)分析能真正支持數(shù)據(jù)的靈活統(tǒng)計需要,滿足多變的業(yè)務數(shù)據(jù)分析場景。
以上問題的關鍵,在于如何解決未來海量業(yè)務數(shù)據(jù)的存儲、靈活處理及深度分析,基于此,我們調研了行業(yè)內(nèi)多家成熟數(shù)據(jù)解決方案,重點考慮京東業(yè)務特點,最終構造了一套完整的京東小程序自定義數(shù)據(jù)分析服務。
接下來,本文將詳細介紹京東小程序自定義數(shù)據(jù)分析服務的整體技術方案和關鍵流程,重點涵蓋動態(tài)規(guī)則配置解析、數(shù)據(jù)存儲設計以及實時數(shù)據(jù)查詢分析等功能的設計和實現(xiàn)。
二、 技術選型
京東小程序的自定義數(shù)據(jù)分析需要一種支持海量數(shù)據(jù)存儲、查詢高效且運維成本較低的數(shù)據(jù)存儲方式,經(jīng)過調研對比發(fā)現(xiàn),ClickHouse以下的三點特征可以很好地滿足我們的技術選型訴求。
1、支持列式存儲和數(shù)據(jù)壓縮
京東小程序自定義數(shù)據(jù)分析需要滿足用戶在系統(tǒng)查詢分析時的查詢執(zhí)行效率,我們期望在百億數(shù)據(jù)集中,秒級返回執(zhí)行的自定義數(shù)據(jù)分析的聚合結果,對比發(fā)現(xiàn),ClickHouse按列存儲的特性便可以極大提升數(shù)據(jù)查詢的效率,因為按列存儲與按行存儲相比,前者可以有效減少查詢時所需掃描的數(shù)據(jù)量,如果數(shù)據(jù)按行存儲,數(shù)據(jù)庫首先會逐行掃描,并獲取每行數(shù)據(jù)的所有字段,再從每一行數(shù)據(jù)中返回查詢所需要的字段,導致會掃描所有的字段。如果數(shù)據(jù)按列組織,數(shù)據(jù)庫可以直接獲取想查詢的列的數(shù)據(jù),從而避免了多余的數(shù)據(jù)行掃描。
針對分析類查詢,通常只需要讀取表的一小部分列。在列式數(shù)據(jù)庫中你可以只讀取你需要的數(shù)據(jù)。例如,如果只需要讀取100列中的5列,這將幫助你最少減少20倍的I/O消耗。
ClickHouse采用的壓縮算法可以將列的數(shù)據(jù)進行壓縮處理,數(shù)據(jù)中的重復項越多,則壓縮率越高;壓縮率越高,則數(shù)據(jù)體量越小;而數(shù)據(jù)體量越小,則數(shù)據(jù)在網(wǎng)絡中的傳輸越快,對網(wǎng)絡帶寬和磁盤I/O的壓力也就會進一步地變小。
2、MPP架構,支持分布式水平拓展
京東小程序自定義數(shù)據(jù)分析服務需要支持水平的拓展。因為隨時業(yè)務的發(fā)展,小程序的數(shù)據(jù)量勢必會日益龐大,調研發(fā)現(xiàn),ClickHouse天然具備分布式存儲的特點,它本身是一款MPP(Massively Parallel Processing)架構的列式存儲數(shù)據(jù)庫,支持大規(guī)模并行處理,以多主對等的扁平架構,保證了海量數(shù)據(jù)在各個節(jié)點的分布式存儲。
這樣對于我們后期的業(yè)務數(shù)據(jù)的拓展存儲提供了必要的保障,只需簡單增加節(jié)點,即可實現(xiàn)水平擴容,極大地降低了運維的成本。
在ClickHouse中,數(shù)據(jù)可以保存在不同的shard上,每一個shard都由一組用于容錯的replica組成,查詢可以并行地在所有shard上進行處理,如下圖Node1和Node2均為主shard,互為replicate,然而這些對用戶來說完全是透明的。
3、多樣化的表存儲引擎
京東小程序自定義數(shù)據(jù)分析的場景較多,涉及點擊、瀏覽、曝光和訂單等四大類分析場景,每種場景都有獨特且常見的統(tǒng)計需要,比如常見的計算去重用戶數(shù)、求和金額、求金額平均值或最大值等,而在ClickHouse中可以針對表設置對應的表引擎,表引擎決定了表存儲在哪里、以何種方式進行存儲以及支持的查詢方式。同時,表引擎可以結合ClickHouse的物化視圖使用,能夠達到非常好的查詢效果。
ClickHouse共擁有合并樹、內(nèi)存、文件、接口和其他6大類20多種表引擎。其中每一種表引擎都有著各自的特點和適用的場景,對于簡單的場景,可直接使用簡單的引擎降低運維成本,而復雜的場景也有合適的選擇。
比如,MergeTree家族的ReplacingMergeTree引擎,它會刪除排序鍵值相同的重復項。數(shù)據(jù)的去重只會在數(shù)據(jù)合并期間進行,合并會在后臺一個不確定的時間進行,因此你無法預先作出計劃。因此,ReplacingMergeTree 適用于在后臺清除重復的數(shù)據(jù)以節(jié)省空間,但是它不保證沒有重復的數(shù)據(jù)出現(xiàn)。
SummingMergeTree會把行主鍵相同的行合并為一行,計算求和值,該行包含了被合并的行中具有數(shù)值數(shù)據(jù)類型的列的匯總值。
AggregatingMergeTree在合并分區(qū)的時候按照定義的條件聚合數(shù)據(jù),將需要聚合的數(shù)據(jù)預先計算出來,在聚合查詢時直接使用結果數(shù)據(jù)。
三、 京東小程序自定義數(shù)據(jù)分析的整體架構
了解了ClickHouse相關特性后,接下來介紹完整的京東小程序自定義數(shù)據(jù)分析的技術方案。
整體的自定義數(shù)據(jù)分析功能主要包含自定義數(shù)據(jù)上報、數(shù)據(jù)加工計算以及數(shù)據(jù)存儲三大層次結構。其中最核心的問題是上報的數(shù)據(jù)如何基于自定義的配置規(guī)則進行匹配關聯(lián)查詢。而解決辦法是在上報的數(shù)據(jù)記錄中可以采用一個event_id(事件id)來標識某次上報請求數(shù)據(jù),然后將業(yè)務字段放在map結構中,如下數(shù)據(jù)結構所示,這樣可以實現(xiàn)業(yè)務數(shù)據(jù)字段的橫向拓展,又能輕松定位到上報的數(shù)據(jù)記錄。
上報數(shù)據(jù)的通道主要包括網(wǎng)關http實時數(shù)據(jù)通道以及子午線客戶端埋點通道,將這些數(shù)據(jù)統(tǒng)一下發(fā)至實時數(shù)倉或者HDFS離線數(shù)倉。
通過中間層的數(shù)據(jù)流轉,執(zhí)行Flink實時計算或者MapReduce的離線計算,從而對原始的上報數(shù)據(jù)進行過濾、加工計算,最終批量寫入至ClickHouse來實現(xiàn)數(shù)據(jù)的最終持久化存儲。
至此,可以基于前端界面上配置的自定義事件和查詢指標、過濾條件、分組條件等自定義查詢規(guī)則,實現(xiàn)數(shù)據(jù)的在線查詢分析。效果展示如下圖所示。
四、 京東小程序自定義數(shù)據(jù)分析的流程設計
那么,規(guī)則引擎服務如何基于自定義規(guī)則動態(tài)解析處用戶上報的數(shù)據(jù)的呢?規(guī)則引擎的執(zhí)行流程主要包含兩部分,包含自定義數(shù)據(jù)上報屬性的配置寫入以及自定義數(shù)據(jù)分析兩個核心流程。
首先,需要將上報的屬性配置保存至數(shù)據(jù)庫進行持久化存儲,當進行實時數(shù)據(jù)查詢時,會先獲取以上的事件規(guī)則和指標,之后,規(guī)則引擎會構建查詢sql腳本推送至執(zhí)行引擎,執(zhí)行引擎下發(fā)sql腳本至ClickHouse集群去執(zhí)行數(shù)據(jù)的查詢并返回結果至前端,最后,異步將執(zhí)行結果寫入緩存,并設置數(shù)據(jù)有效期,便于提升下次查詢效率。整體的解析執(zhí)行流程如下圖所示。
五、 京東小程序自定義數(shù)據(jù)分析的表設計
ClickHouse的表分為本地表和分布式表,分布式表是一個邏輯上的表, 可以理解為數(shù)據(jù)庫中的視圖, 一般查詢都查詢分布式表。分布式表引擎會將我們的查詢請求路由本地表進行查詢, 然后進行匯總最終返回給用戶。本地表是實際存儲數(shù)據(jù)的表,本地表和分布式表的關系如下圖所示,在寫入和讀取數(shù)據(jù)時通過nginx實現(xiàn)請求的負載均衡,防止出現(xiàn)寫入和讀取不均衡的情況。
以京東小程序自定義點擊事件的數(shù)據(jù)統(tǒng)計場景為例,我們創(chuàng)建對應的本地表vapp_analysis_local和分布式表vapp_analysis_dist如下圖所示。
本地表:
分布式表:
舉例說明,根據(jù)京東小程序點擊事件的數(shù)據(jù)存儲特點,我們做了如下的表設計:
- 設置主節(jié)點數(shù)和副本數(shù)。shard屬性設置節(jié)點的主數(shù)據(jù)節(jié)點數(shù),replica設置節(jié)點的副本數(shù),從而保證數(shù)據(jù)存儲的多副本高可用。
- 選擇分區(qū)字段。ClickHouse支持分區(qū),分區(qū)字段是每張表整個數(shù)據(jù)目錄最外層結構,可以很大程度加快查詢速度。具體的DDL操作關鍵詞是 PARTITION BY,指的是一個表按照某一列數(shù)據(jù)(比如日期)進行分區(qū),對應到最終的結果就是不同分區(qū)的數(shù)據(jù)會寫入不同的文件中,在我們的業(yè)務場景中是按照數(shù)據(jù)的上報時間取年、月、日按照天來進行分區(qū)的,toYYYYMMDD(report_time)。
- 設置排序規(guī)則。設置合理的數(shù)據(jù)排序規(guī)則可以提升數(shù)據(jù)的查詢效率,數(shù)據(jù)會按照設置的排序字段先后順序來進行存儲,在進行聚合計算時也會按照聚合條件對相鄰數(shù)據(jù)進行計算。在我們的業(yè)務場景中采用的是小程序的AppID來作為排序的規(guī)則,小程序AppID是每個小程序的唯一標識,在查詢數(shù)據(jù)時絕大部分場景會以AppID的維度進行數(shù)據(jù)的查詢。所以,采用AppID作為排序字段可以很大程度上提升我們的數(shù)據(jù)聚合運算效率。
- 設置表引擎。在點擊事件的場景中,我們設置的支持多副本的ReplicatedMergeTree引擎,可以支持數(shù)據(jù)的多副本存儲,保證數(shù)據(jù)的高可用。
在以上的表設計中,content字段非常關鍵。我們將上報的自定義數(shù)據(jù)存儲到表中的content字段中,并以json結構進行存儲,這樣即可支持上報字段的水平拓展。當規(guī)則引擎將動態(tài)生成的sql腳本下發(fā)至Clickhouse執(zhí)行查詢時,利用Clickhouse的json解析函數(shù)JSONExtractString進行取值轉換,這樣就可以非常容易得到我們想要分析的指定的業(yè)務字段。
舉例說明,當我們想從京東小程序點擊事件表中獲取事件編碼為applets_buy的金額字段amount時,基于規(guī)則解析引擎構建并下發(fā)至ClickHouse的動態(tài)腳本即為如下形式,這樣便可實現(xiàn)上報字段的動態(tài)提取。
六、 京東小程序自定義數(shù)據(jù)分析的監(jiān)控
在整個自定義數(shù)據(jù)分析的鏈路中,涉及的環(huán)節(jié)較多,需要有良好的監(jiān)控機制,來保證系統(tǒng)功能的穩(wěn)定運行。
針對MQ消息隊列、Flink實時計算任務、ClickHouse存儲等中間件的監(jiān)控,我們采取的是Grafana提供的可視化監(jiān)控能力。如下圖所示,這樣可以直觀地看到諸如CPU、內(nèi)存、磁盤的I/O、磁盤使用率等情況。
同時,針對京東小程序運行時的監(jiān)控,我們提供了一套完整的監(jiān)控告警機制,支持配置自定義告警規(guī)則,來幫助我們及時發(fā)現(xiàn)京東小程序自身異常頁面數(shù)據(jù)、性能數(shù)據(jù)以及網(wǎng)絡請求數(shù)據(jù)等異常數(shù)據(jù)信息,目前已可以監(jiān)控到線上所有小程序的異常數(shù)據(jù)和性能運行情況,以單個小程序為例,監(jiān)控的情況如下圖所示。
基于以上兩種監(jiān)控手段,可以幫忙我們時刻掌握京東小程序在整個鏈路中的性能數(shù)據(jù)的波動、及時發(fā)現(xiàn)性能瓶頸、迅速定位運行中出現(xiàn)的各種問題,從而為整個京東小程序的業(yè)務發(fā)展保駕護航。
七、 總結展望
京東小程序自定義數(shù)據(jù)分析服務所提供的高效靈活的處理能力,不僅極大地提高了京東小程序數(shù)據(jù)平臺的完整性,也為持續(xù)沉淀行業(yè)業(yè)務數(shù)據(jù)提供了完善的保障,預計首批落地支持50+核心小程序的業(yè)務自定義數(shù)據(jù)上報、分析及可視化,完整串聯(lián)用戶在小程序內(nèi)外的行為路徑,支持商家精細化運營的需要。
京東小程序數(shù)據(jù)能力已經(jīng)完成了從0到1的突破,未來將會致力于打造京東小程序智能數(shù)據(jù)分析模型,從而實現(xiàn)從1到N的飛躍。最終幫助更多京東小程序商家不斷優(yōu)化運營策略,降低數(shù)據(jù)分析成本,提升業(yè)務產(chǎn)能及效率!