Kylin 大數(shù)據(jù)下的OLAP解決方案和行業(yè)典型應(yīng)用
點擊上方藍色字體,選擇“設(shè)為星標(biāo)”

最近工作中應(yīng)用到了 Kylin,因此調(diào)研了 Kylin的原理和行業(yè)應(yīng)用。本文參考了官網(wǎng)和眾多其他公司中 Kylin的應(yīng)用案例,文末給出了出處,希望對大家有幫助。
Apache Kylin的原理和技術(shù)架構(gòu)
Apache Kylin 從數(shù)據(jù)倉庫中最常用的Hive中讀取源數(shù)據(jù),使用 MapReduce作為Cube構(gòu)建的引擎,并把預(yù)計算結(jié)果保存在HBase中,對外暴露Rest API/JDBC/ODBC的查詢接口。
Apache Kylin系統(tǒng)主要可以分為在線查詢和離線構(gòu)建兩部分,具體架構(gòu)圖如下:

Apache Kylin在百度地圖的實踐
對于 Apache Kylin 在實際生產(chǎn)環(huán)境中的應(yīng)用,在國內(nèi),百度地圖數(shù)據(jù)智能組是最早的一批實踐者之一。目前,百度地圖大數(shù)據(jù) OLAP 多維分析平臺承載百度地圖內(nèi)部多個基于 Apache Kylin 引擎的億級多維分析查詢項目,共計約 80 個 cube,平均半年時間的歷史數(shù)據(jù),共計約 50 億行的源數(shù)據(jù)規(guī)模,單表最大數(shù)據(jù)量為 20 億 + 條源數(shù)據(jù),滿足大時間區(qū)間、復(fù)雜條件過濾、多維匯總聚合的單條 SQL 查詢毫秒級響應(yīng),較為高效地解決了億級大數(shù)據(jù)交互查詢的性能需求。
Kylin 有效解決的痛點問題:
痛點一:百億級海量數(shù)據(jù)多維指標(biāo)動態(tài)計算耗時問題,Apache Kylin 通過預(yù)計算生成 Cube 結(jié)果數(shù)據(jù)集并存儲到 HBase 的方式解決。
痛點二:復(fù)雜條件篩選問題,用戶查詢時,Apache Kylin 利用 router 查找算法及優(yōu)化的 HBase Coprocessor 解決;
痛點三:跨月、季度、年等大時間區(qū)間查詢問題,對于預(yù)計算結(jié)果的存儲,Apache Kylin 利用 Cube 的 Data Segment 分區(qū)存儲管理解決。
百度地圖大數(shù)據(jù) OLAP 平臺系統(tǒng)架構(gòu)

主要模塊包括:
數(shù)據(jù)接入:主要負責(zé)從數(shù)據(jù)倉庫端獲取業(yè)務(wù)所需的最細粒度的事實表數(shù)據(jù)。
任務(wù)管理:主要負責(zé)Cube 的相關(guān)任務(wù)的執(zhí)行、管理等。
任務(wù)監(jiān)控:主要負責(zé)Cube 任務(wù)在執(zhí)行過程中的狀態(tài)及相應(yīng)的操作管理。
集群監(jiān)控:主要包括Hadoop 生態(tài)進程的監(jiān)控及Kylin 進程的監(jiān)控。
基于倉庫端 join 好的 fact 事實表建 Cube,減少對小規(guī)模集群帶來的 hive join 壓力
對于 Cube 的設(shè)計,官方有專門的相關(guān)文檔說明,里面有較多的指導(dǎo)經(jīng)驗,比如: cube 的維度最好不要超過 15 個, 對于 cardinality 較大的維度放在前面,維度的值不要過大,維度 Hierarchy 的設(shè)置等等。
實踐中,百度地圖將某個產(chǎn)品需求分為多個頁面進行開發(fā),每個頁面查詢主要基于事實表建的 cube,每個頁面對應(yīng)多張維度表和 1 張事實表,維度表放在 MySQL 端,由數(shù)據(jù)倉庫端統(tǒng)一管理,事實表計算后存放在 HDFS 中,事實表中不存儲維度的名稱,僅存儲維度的 id,主要基于 3 方面考慮:
第一:減少事實表體積
第二:由于我們的 Hadoop 集群是自己單獨部署的小集群,MapReduce 計算能力有限,join 操作希望在倉庫端完成,避免給 Kylin 集群帶來的 Hive join 等計算壓力
第三:減少回溯代價
假設(shè)我們把維度名稱也存在 Cube 中,如果維度名稱變化必然導(dǎo)致整個 cube 的回溯,代價很大。這里可能有人會問,事實表中只有維度 id 沒有維度 name,假設(shè)我們需要 join 得到查詢結(jié)果中含有維度 name 的記錄,怎么辦呢?對于某個產(chǎn)品的 1 個頁面,我們查詢時傳到后臺的是維度 id,維度 id 對應(yīng)的維度 name 來自 MySQL 中的維度表,可以將維度 name 查詢出來并和維度 id 保存為 1 個維度 map 待后續(xù)使用。同時,一個頁面的可視范圍有限,查詢結(jié)果雖然總量很多,但是每一頁返回的滿足條件的事實表記錄結(jié)果有限,那么,我們可以通過之前保存的維度 map 來映射每列 id 對應(yīng)的名稱,相當(dāng)于在前端邏輯中完成了傳統(tǒng)的 id 和 name 的 join 操作。
Aggregation cube 輔助中高維度指標(biāo)計算,解決向上匯總計算數(shù)據(jù)膨脹問題
比如我們的事實表有個 detail 分區(qū)數(shù)據(jù),detail 分區(qū)包含最細粒度 os 和 appversion 兩個維度的數(shù)據(jù) (注意: cuid 維度的計算在倉庫端處理),我們的 cube 設(shè)計也選擇 os 和 appversion,hierarchy 層次結(jié)構(gòu)上,os 是 appversion 的父親節(jié)點,從 os+appversion(group by os, appversion) 組合維度來看,統(tǒng)計的用戶量沒有問題,但是按照 os(group by os) 單維度統(tǒng)計用戶量時,會從基于這個 detail 分區(qū)建立的 cube 向上匯總計算,設(shè)上午用戶使用的是 android 8.0 版本,下午大量用戶升級到 android 8.1 版本,android 8.0 組合維度 + android 8.1 組合維度向上計算匯總得到 os=android(group by os, where os=android) 單維度用戶,數(shù)據(jù)會膨脹且數(shù)據(jù)不準(zhǔn)確。因此我們?yōu)槭聦嵄碓黾右粋€ agg 分區(qū),agg 分區(qū)包含已經(jīng)從 cuid 粒度 group by 去重后計算好的 os 單維度結(jié)果。這樣,當(dāng)用戶請求 os 維度匯總的情況下,Apache Kylin 會根據(jù) router 算法,計算出符合條件的候選 cube 集合,并按照權(quán)重進行優(yōu)選級排序 (熟悉 MicroStrategy 等 BI 產(chǎn)品的同學(xué)應(yīng)該知道這類案例),選擇器會選中基于 agg 分區(qū)建立的 os 單維度 agg cube,而不從 detail 這個分區(qū)建立的 cube 來自底向上從最細粒度往高匯總,從而保證了數(shù)據(jù)的正確性。
新增留存類分析,如何更高效更新歷史記錄
對應(yīng)小規(guī)模集群,計算資源是非常寶貴的,假設(shè)我們對于某個項目的留存分析到了日對 1 日到日對 30 日,日對 1 周到日對 4 周,日對 1 月到日對 4 月,周對 1 周到周對 4 周,月對 1 月到月對 4 月。那么對于傳統(tǒng)的存儲方案,我們將遇到問題。
假如今天是 2015-12-02,我們計算實際得到的是 2015-12-01 的數(shù)據(jù)。

此方案的思路是,當(dāng)今天是2015-12-02,實際是2015-12-01 的數(shù)據(jù),如上示例存儲,但日對第n 日的留存表示的是n 日前對應(yīng)的那個日期的留存量,相當(dāng)于旋轉(zhuǎn)了紅色對角線。
此方案的優(yōu)勢:
如果要查看某個時間范圍內(nèi)的某 1 個指標(biāo),直接選擇該范圍的該列指標(biāo)即可
如果今后增加新的留存,比如半年留存,年留存等指標(biāo),不需要級聯(lián)更新歷史天數(shù)的數(shù)據(jù),只需要更新 2015-12-01 這 1 天的數(shù)據(jù),時間復(fù)雜度 O(1) 不變,對物理機器資源要求不高。
此方案的缺點:
如果涉及到某 1 天或者某個時間范圍的多列指標(biāo)查詢,需要前端開發(fā)留存分析特殊處理邏輯,根據(jù)相應(yīng)的時間窗口滑動,從不同的行,選擇不同的列,然后渲染到前端頁面。
Apache Kylin在鏈家的實踐
鏈家Kylin平臺的架構(gòu)如圖:

如上,為鏈家 Olap 平臺結(jié)構(gòu),于 16 年底搭建。Kylin 采用集群部署模式,共部署 6 臺機器,3 臺用于分布式構(gòu)建 Cube,3 臺用于負載均衡查詢,query 單臺可用內(nèi)存限制在 80G。同時,計算集群一旦運行大任務(wù),內(nèi)存壓力大的時候,HBase 就會性能非常差,為避免和計算集群互相影響,Kylin 集群依賴獨立的 Hbase 集群。同時,對 Hbase 集群做了相應(yīng)的優(yōu)化,包括:讀寫分離、SSD_FIRST 優(yōu)先讀取遠程 SSD、并對依賴的 hdfs 做了相應(yīng)優(yōu)化。
由于 Kylin 只專注預(yù)計算,不保存明細數(shù)據(jù),對于即席查詢和明細查詢,通過自研 QE 引擎實現(xiàn),底層依賴 spark、presto、hive,通過特定規(guī)則,路由到相應(yīng)查詢引擎執(zhí)行查詢。多維分析查詢,由 Kylin 集群提供查詢服務(wù),可實現(xiàn)簡單的實時聚合計算。
當(dāng)前 Kylin 主要查詢方為指標(biāo) API 平臺,能根據(jù)查詢 sql 特征,做相應(yīng)緩存。指標(biāo) API 作為數(shù)據(jù)統(tǒng)一出口,衍生出其他一些業(yè)務(wù)產(chǎn)品。使用統(tǒng)計,如下:Cube 數(shù)量 500+,覆蓋公司 12 個業(yè)務(wù)線。Cube 存儲總量 200+TB,數(shù)據(jù)行萬億級,單 Cube 最大 40+億行。日查詢量 27 萬+,緩存不命中情況下,時延 < 500ms(70%), < 1s(90%),少量復(fù)雜 sql 查詢耗時 10s 左右。
當(dāng)前,kylin 在用版本為 1.6,最新版本為 2.3。自 2.0 版本之后,又新增了一些新的特性,配置文件和屬性也做了一些調(diào)整。由于,Cube 數(shù)據(jù)量大,涉及業(yè)務(wù)方多,在當(dāng)前無明顯瓶頸的情況下,沒有實時更新新版本。但是,引入了 2.0+新增的一些重要特性,如分布式構(gòu)建和分布式鎖。
鏈家維護了自己的一套 Kylin 代碼,使用過程中,針對特定場景的進行一些優(yōu)化開發(fā),包括:
支持分布式構(gòu)建。原生 kylin 是只能有一臺機器進行構(gòu)建。的當(dāng) kylin 上的 cube 越來越多,單臺機器顯然不能滿足任務(wù)需求,除了任務(wù)數(shù)據(jù)有限制,任務(wù)多時也會互相影響數(shù)據(jù)構(gòu)建的效率。通過修改 kylin 的任務(wù)調(diào)度策略,支持了多臺機器同時構(gòu)建數(shù)據(jù)。使 kylin 的構(gòu)建能力可以橫向擴展,來保證數(shù)據(jù)構(gòu)建;
優(yōu)化構(gòu)建時字典下載策略。原生 kylin 在 build cubiod data 時用的字典,會將該字段的全部字典下載到節(jié)點上,當(dāng)字段的字典數(shù)量很多或者字典文件很大時,會在文件傳輸上消耗很多不必要的時間。通過修改代碼,使任務(wù)只下載需要的字典文件,從而減少文件傳輸時間消耗,加快構(gòu)建;
全局字典鎖,在同一 Cube 所任務(wù)構(gòu)建時,由于共享全局字典鎖,當(dāng)某執(zhí)行任務(wù)異常時,會導(dǎo)致其他任務(wù)獲取不到鎖,此 bug 已修復(fù)并提交官方;
支持設(shè)置 Cube 強制關(guān)聯(lián)維表,過濾事實表中無效的維度數(shù)據(jù)。kylin 創(chuàng)建的臨時表作為數(shù)據(jù)源。當(dāng)使用 olap 表和維表關(guān)聯(lián)字段作為維度時,會默認不關(guān)聯(lián)維表,直接使用 olap 中的字段做維度。而在 Build Cube 這一步又會使用維表的字典來轉(zhuǎn)換維度的值。如果 olap 中的值維表中沒有就會產(chǎn)生問題。我們通過增加配置項,可以使 kylin 強制關(guān)聯(lián)維表,來過濾掉 olap 表中的臟數(shù)據(jù);
Kylin query 機器,查詢或者聚合,會加載大量的數(shù)據(jù)到內(nèi)存,內(nèi)存占用大,甚至存在頻繁 Full GC 的情況。這種情況下,CMS 垃圾回收表現(xiàn)不是很好,因此更換為 G1 收集器,盡量做到 STW 時間可控,并及時調(diào)優(yōu)。
Kylin在滴滴OLAP引擎中的應(yīng)用
下圖為 Kylin 在滴滴 OLAP 引擎中的部署情況,Kylin 集群包含 2 臺分布式構(gòu)建節(jié)點、8 臺查詢節(jié)點,其中 2 臺查詢節(jié)點作為集群接口承接 REST 請求,REST 請求主要包含兩類:構(gòu)建作業(yè)狀態(tài)查詢和創(chuàng)建類操作,創(chuàng)建類操作如裝載表、建模、創(chuàng)建立方體以及對等的刪除操作等等。對于構(gòu)建作業(yè)狀態(tài)查詢輪詢請求兩臺節(jié)點,而對創(chuàng)建類操作則請求其中固定的一臺節(jié)點,另一臺作為 Standby 存在,這樣設(shè)計的主要目的是避免集群接口的單點問題,同時解決因 Kylin 集群元數(shù)據(jù)同步機制導(dǎo)致的可能出現(xiàn)的創(chuàng)建類操作失敗問題。

Kylin 作為固化分析場景引擎,主要負責(zé)對有聚合緩存需求的表進行查詢加速。什么樣的表會有這樣的需求呢?
報表類產(chǎn)品使用的表
經(jīng) OLAP 引擎數(shù)據(jù)轉(zhuǎn)移決策識別認為需要進行聚合緩存的表
前者不難理解,后者則如引擎中的表,表數(shù)據(jù)規(guī)模較大,且被頻繁執(zhí)行某種聚合分析,在一段時間內(nèi)達到一定的頻次,引擎會識別并認為該表需要執(zhí)行聚合緩存,進而觸發(fā)調(diào)度將數(shù)據(jù)“復(fù)制”到 Kylin。這樣,下次針對該表的聚合分析如果可被 Kylin 的聚合緩存覆蓋,就會直接查詢 Kylin 中的聚合數(shù)據(jù)“副本”而非原始的明細數(shù)據(jù)“副本”。
Apache Kylin 在場景引擎中的使用效果
目前,Kylin 集群維護了700+ 的立方體,每日運行2000+ 的構(gòu)建作業(yè),平均構(gòu)建時長37 分鐘,立方體存儲總量30+TB(已去除HDFS 副本影響);對未使用緩存的查詢進行統(tǒng)計,80% 的查詢耗時小于500ms,90% 的查詢耗時小于2.8 秒。需要說明的是,由于OLAP 引擎中“數(shù)據(jù)轉(zhuǎn)移決策”模塊會根據(jù)查詢場景觸發(fā)數(shù)據(jù)“復(fù)制”到Kylin 中來,在近期的統(tǒng)計中,立方體數(shù)量一度會達到1100+。
在業(yè)務(wù)方面,Kylin 間接服務(wù)了下游數(shù)易(面向全公司的報表類數(shù)據(jù)產(chǎn)品)、開放平臺(面向全公司的查詢?nèi)肟冢┑榷鄠€重要數(shù)據(jù)產(chǎn)品,覆蓋了快車、專車等十多個業(yè)務(wù)線的分析使用,間接用戶3000+,Kylin 的引入為用戶提供了穩(wěn)定、可靠、高效的固化分析性能。
使用 Apache Kylin 遇到的挑戰(zhàn)
滴滴使用 Kylin 的方式與傳統(tǒng)方式有異,Kylin 在架構(gòu)設(shè)計上與業(yè)務(wù)緊耦合,傳統(tǒng)方式中業(yè)務(wù)分析人員基于 Kylin 建模、構(gòu)建立方體(Cube),然后執(zhí)行分析查詢。但滴滴將 Kylin 作為固化分析場景下的引擎使用,提供針對表的聚合緩存服務(wù),這樣作為一個通用數(shù)據(jù)組件的 Kylin 就剝離了業(yè)務(wù)屬性,且與用戶相割裂,對外透明。
在最初的使用中,由于沒有控制 OLAP 引擎的內(nèi)部并發(fā),來自調(diào)度的聚合緩存任務(wù)會在某些情況下高并發(fā)地執(zhí)行 Kylin 的表加載、模型和立方體的創(chuàng)建,因為 Kylin Project 元數(shù)據(jù)的更新機制導(dǎo)致操作存在失敗的可能。當(dāng)前,我們通過在 OLAP 引擎內(nèi)部使用隊列在一定程度上緩解了問題的發(fā)生,此外,結(jié)合重試機制,基本可以保證操作的成功完成。最后我們也注意到,該問題在最新的 Kylin 版本中已經(jīng)進行了修復(fù)。
另外,Kylin 默認地,在刪除立方體時不會卸載 HBase 中的 Segment 表,而需定期執(zhí)行腳本進行清理。這樣,就導(dǎo)致引擎運行時及時卸載無效的立方體無法級聯(lián)到 HBase,給 HBase 造成了較大的運維壓力。因此我們也對源碼進行了調(diào)整,在立方體刪除時增加了 HBase Segment 表清理的功能,等等。

版權(quán)聲明:
文章不錯?點個【在看】吧!??




