[魅族]大數據多維分析引擎在MEIZU的實踐

//
【微學堂】大數據多維分析引擎在MEIZU的實踐
http://mp.weixin.qq.com/s?src=3&timestamp=1486433778&ver=1&signature=na0ytajPH-136OH6OuYhCpd5mKGJzLdNOWunnkPssO1KQxFA69YhoGqkMO9K7tLYhFR8Pb5x2XrgAYsUjWimIThmrrSMHXd9GEH21xUrK91yydHRp52nQWhrqANCOECY3vYnV60MTgJpWDfL4imhlljOo--rqq2IYpujGwEhs=

我是來自魅族科技的趙天爍,今晚跟大家分享apache kylin在魅族的一些實踐。
閑話不多說我就直接進入正題了~

相信群里的各位同學應該都是對數據庫技術感興趣的,apache kylin作為大數據分析引擎這一塊近年來崛起的新星已經受到越來越多人的關注。我今天的內容主要分為以下幾個方面:
Kylin的基本 **介紹 **
Kylin核心概念和特性
** Kylin **在魅族的應用案例(場景+優化實踐)

在大數據的時代,越來越多的企業開始使用Hadoop管理數據,但是現有的業務分析工具(如Tableau,Microstrategy等)往往存在很大的局限,如難以水平擴展、無法處理超大規模數據、缺少對Hadoop的支持;Kylin就是為了解決這些問題而設計的。Apache Kylin,中文名麒(shen)麟(shou) 是Hadoop動物園的重要成員。Apache Kylin是一個開源的分布式分析引擎,最初由eBay的幾位華人工程師開發貢獻至開源社區,這也是它取名麒麟的一個重要原因,kylin是為數不多的由華人貢獻至apache社區并能夠成為頂級項目的。它提供Hadoop之上的SQL查詢接口及多維分析(OLAP)能力以支持大規模數據,能夠處理TB乃至PB級別的分析任務,能夠在亞秒級查詢巨大的Hive表,并支持高并發。
[圖片上傳中。。。(1)]
Apache Kylin于2014年10月在github開源,并很快在2014年11月加入Apache孵化器,于2015年11月正式畢業成為Apache頂級項目,也成為首個完全由中國團隊設計開發的Apache頂級項目。于2016年3月,Apache Kylin核心開發成員創建了Kyligence公司,力求更好地推動項目和社區的快速發展。

Apache Kylin于2014年10月在github開源,并很快在2014年11月加入Apache孵化器,于2015年11月正式畢業成為Apache頂級項目,也成為首個完全由中國團隊設計開發的Apache頂級項目。于2016年3月,Apache Kylin核心開發成員創建了Kyligence公司,力求更好地推動項目和社區的快速發展。

Kyligence是一家專注于大數據分析領域創新的數據科技公司,提供基于Apache Kylin的企業級智能分析平臺及產品,以及可靠、專業、源碼級的商業化支持;并推出Apache Kylin開發者培訓,頒發全球唯一的Apache Kylin開發者認證證書。

這里插一句題外話,在做分析引擎選型的時候,除了項目本身的成熟度之外,社區的活躍度和是否有一家商業公司在背后推動一直是我的一個重要的選擇標準,商業化公司在開源技術的組織,標準化,推廣等各個方面都能夠彌補社區的不足之處

剛才對kylin做了一些基本的背景介紹,接下來,我們來逐步深入的探究一下kylin究竟是如何能夠做到在PB級的數據量下提供亞秒級的查詢響應的

首先,為了更好的適應大數據環境,Kylin從數據倉庫中最常用的Hive中讀取源數據,使用 MapReduce作為Cube構建的引擎,并把預計算結果保存在HBase中,對外暴露Rest API/JDBC/ODBC的查詢接口。因為Kylin支持標準的ANSI SQL,所以可以和常用分析工具(如Tableau、Excel等)進行無縫對接。
Kylin的架構圖

簡單來說,Kylin的核心思想是預計算,即對多維分析可能用到的度量進行預計算,將計算好的結果保存成Cube,供查詢時直接訪問。把高復雜度的聚合運算、多表連接等操作轉換成對預計算結果的查詢,這決定了Kylin能夠擁有很好的快速查詢和高并發能力。

下面我們聊一聊kylin的一些基本原理

上圖所示就是一個Cube的例子,假設我們有4個dimension,這個Cube中每個節點(稱作Cuboid)都是這4個dimension的不同組合,每個組合定義了一組分析的dimension(如group by),measure的聚合結果就保存在這每個Cuboid上。查詢時根據SQL找到對應的Cuboid,讀取measure的值,即可返回。

算法優點
此算法充分利用了MapReduce的能力,處理了中間復雜的排序和洗牌工作,故而算法代碼清晰簡單,易于維護;

受益于Hadoop的日趨成熟,此算法對集群要求低,運行穩定;在內部維護Kylin的過程中,很少遇到在這幾步出錯的情況;即便是在Hadoop集群比較繁忙的時候,任務也能完成。

算法缺點
當Cube有比較多維度的時候,所需要的MapReduce任務也相應增加;由于Hadoop的任務調度需要耗費額外資源,特別是集群較龐大的時候,反復遞交任務造成的額外開銷會相當可觀;

由于Mapper不做預聚合,此算法會對Hadoop MapReduce輸出較多數據; 雖然已經使用了Combiner來減少從Mapper端到Reducer端的數據傳輸,所有數據依然需要通過Hadoop MapReduce來排序和組合才能被聚合,無形之中增加了集群的壓力;

對HDFS的讀寫操作較多:由于每一層計算的輸出會用做下一層計算的輸入,這些Key-Value需要寫到HDFS上;當所有計算都完成后,Kylin還需要額外的一輪任務將這些文件轉成HBase的HFile格式,以導入到HBase中去;這些頻繁的對HDFS的讀寫操作都是使得Cube構建的整體時間變長的重要原因

總體而言,該算法雖然簡單清晰易于維護,但是效率較低,尤其是當Cube維度數較大的時候。
[圖片上傳中。。。(2)]
Fast Cubing是1.5之后的版本新增的一種cube構建方式,最大化利用Mapper端的CPU和內存,對分配的數據塊,將需要的組合全都做計算后再輸出給Reducer; 由Reducer再做一次合并(merge),從而計算出完整數據的所有組合。如此,經過一輪Map-Reduce就完成了以前需要N輪的Cube計算
[圖片上傳中。。。(3)]
這種算法還有另外一個優點,如上圖所示:第一步會計算Base Cuboid(所有維度都有的組合),再基于它計算減少一個維度的組合。

基于parent節點計算child節點,可以重用之前的計算結果;當計算child節點時,需要parent節點的值盡可能留在內存中; 如果child節點還有child,那么遞歸向下,所以它是一個深度優先遍歷。當有一個節點沒有child,或者它的所有child都已經計算完,這時候它就可以被輸出,占用的內存就可以釋放。

如果內存夠的話,可以多線程并行向下聚合。如此可以最大限度地把計算發生在Mapper這一端,一方面減少shuffle的數據量,另一方面減少Reducer端的計算量。

接下來我們看一下kylin是如何存儲這些cube的數據的

[圖片上傳中。。。(4)]
MapReduce的計算結果最終保存到HBase中,HBase中每行記錄的Rowkey由dimension組成,measure會保存在column family中。為了減小存儲代價,這里會對dimension和measure進行編碼。查詢階段,利用HBase列存儲的特性就可以保證Kylin有良好的快速響應和高并發。

有了這些預計算的結果,當收到用戶的SQL請求,Kylin會將SQL轉換成查詢計劃(Apache calcite),把本該進行的Join、Sum、Count Distinct等操作改寫成HBase的get和scan的查詢操作。
[圖片上傳中。。。(5)]
相比于很多其他開源分析引擎只開放出來一個基于console的簡單交互入口的內核相比,kylin把一個集成了簡單web-IDE,cube創建編輯,building過程監控和管理、系統配置、權限管理的一個相對完善的管理界面都打包在了kylin的開源發布包中,這使得上手使用kylin會變得非常簡單。
[圖片上傳中。。。(6)]
Kylin提供了一套基于完整的REST API,并且支持符合ANSI SQL標準的語法以及JDBC、ODBC的驅動,這樣我們可以非常方便的將現有的應用切換到kylin上面來,如果有需要的,可以使用kylin的REST API把cube的構建過程集成到我們自己的內部平臺當中去,這些緊靠行業標準的選擇也是kylin能夠快速躥紅的一個重要原因
不那么新的新特性---Parallel Scan

[圖片上傳中。。。(7)]
1.5之后的一個版本中,kylin對HBase存儲結構進行了調整,將大的Cuboid分片存儲,將線性掃描改良為并行掃描。基于上萬查詢進行了測試對比結果顯示,分片的存儲結構能夠極大提速原本較慢的查詢5-10倍,但對原本較快的查詢提速不明顯,綜合起來平均提速為2倍左右
實驗中的feature終于轉正---Streaming Cubing

[圖片上傳中。。。(8)]
Kylin從1.5早期的版本中就開始實驗一種Streaming Cubing的方式,當時的實現方式無愧于實驗feature的稱號,我們也簡單測試過,日常運維各種問題,mini-batch進程crash、數據丟失、一但crash基本上就得重頭來過,數據不可能恢復,所以那時的streaming cubing還不是一個線上可用的狀態。

雖然看起來可以提高cube的構建效率,大幅度提升數據的實時性,但是由于設計的不合理那時候還不能在生產中使用

最近在1.6中終于有一個看上去很美的streaming cubing實現了。新版用一個MR任務去跑每一個kafka分區,把kafka中的數據寫入HDFS,之后就可以和從hive中build一樣使用通用kylin cube building過程了
[圖片上傳中。。。(9)]

這樣做有以下幾個好處
允許多個segment(一個segment就是hbase中存儲cube數據的一個片段)并發build

允許segment之間出現時間窗口重疊(很重要)

其他不那么新的新特性
支持精確的distinct計數(所有數據類型)---1.5.3

支持針對不同的Project設置不同的MR job運行隊列---1.5.3

Top N指標支持多列group by ---1.5.3

主動監測OOM,將堆棧中的cuboid緩存到本地磁盤---1.5

查詢明細數據(RAW MEASURE)---1.5.2

支持Hive視圖作為lookup 表---1.5.2

綜上,如果大家想要在生產環境中使用kylin的話,推薦大家嘗試1.5以上的版本。

Why Kylin?

剛才聊的都是kylin的功能特性和設計,接下來看看我們為什么要選擇kylin,或者說kylin適合什么樣的場景?

1、平臺體系完善,成熟度高,部署簡單,易用

2、在高并發訪問下保持不錯的性能,隨著數據量和維度組合的增長,性能衰減也不會特別明顯

3、Cube模型的合理設計,可以減少人工配置 ETLjob的數量

4、可以在數據準確度、存儲空間、性能之間靈活調整,找到最適合需求場景的平衡點

5、標準SQL語法+JDBC/ODBC驅動可以很方便的和現有系統做集成

7、社區活躍,有Kyligence這樣的商業公司在背后推動

8、支持準實時的數據更新,未來有準實時OLAP需求也可以復用kylin

9、底層基于已經相對成熟的Hive、HBase,整體技術棧并不復雜,日常運維成本低

hobo文庫本下面是Kylin的架構圖應用場景特征

我們總結了一下日常接入kylin的需求需要滿足的基本特征,這些描述都是基于我們自身的技術體系和需求的特點而決定的,僅供大家參考,并不是一定要這樣

I. 數據量大,同時對查詢性能有需求

數據量不大直接用mysql好了,對查詢性能沒有要求的可以用其他的諸如impala或者spark都可以

II. 數據實時性要求不高(目前最高到小時級更新)

只針對于非實時的cubing,Streaming cubing目前還在研究中,方案成熟后可以很大程度上提高實時性

III. 維度組合和查詢條件組合在可預見的范圍內


由于Cube模型需要預先構建,因此維度的組合和條件必須是可預見的,如果用戶傳入的維度building時沒有包含,自然是查詢報錯了。對于查詢自由度過高的場景還是推薦用hive、spark或者impala

IV. 數據總量大,但條件掃描范圍不會太大的。

不適合需要大范圍模糊搜索排序的場景(類似search),這類場景自然是ES這類搜索引擎的強項,kylin并不擅長。
[圖片上傳中。。。(10)]
上圖中的性能指標都是優化后的,前期剛上線的時候也是經歷了多倫的痛苦優化。

先看看上面那個例子優化前的狀態

優化前:

Cube原始記錄 6億---一個月數據
build后的Cube Size 1.9T
單次查詢掃描一周數據,HBase頻繁超時,Region Server經常被拖死,平均響應時間近30s

維度基本上全選,mandory、維度繼承從來不用,結果如上。。Cube存儲空間相比原始數據膨脹了700倍,Hbase region server一天掛N次,運維小哥苦不堪言。

優化后:
活用Aggregation Groups

http://kylin.apache.org/blog/2016/02/18/new-aggregation-group/

將使用場景進行分組,對應不同的group

大基數維度創建單獨的group,盡量確認需求,收縮條件組合范圍,include中只包含相關的維度

低基數的維度可以單獨建立一個group,加上必選條件維度,把低基數的維度都設置成Mandatory,這樣維度組合出現時kylin會靈活進行內存內二次聚合,但因為這些維度基數都不大,對性能不會影響太多

二選一或多選一的條件維度不要包含在統一個group(比如崩潰時間和上傳時間)

同時有好幾個大基數group的話可以考慮每個group單獨建一個cube(避免cube膨脹,row key結構也更合理)

kylin.query.mem.budget

Rowkey

有日期分區字段的,可以將日期轉成只包含變化范圍的數字:
比如原始格式是字符串的2016-07-15 12:31:25,只保留一個月的數據,同時查詢是按天維度group by 不關心小時分鐘可以把日期轉成yyMMdd ,160715,這樣可以極大的降低維度基數

基數小的維度在前面

低基數的維度盡量用dict編碼(100w以內)

合理使用層級維度/派生維度
http://kylin.apache.org/docs15/howto/howto_optimize_cubes.html

Kev1nZ:優化后效果


Cube build后大小降低到500G上下
50%的查詢性能在2s以內
Cube build時間縮短30%

本來希望整理一些streaming cubing的實踐和優化相關的內容,但是由于社區里的很多實踐最近變化比較大,還不太穩定,以后等穩定過之后再有機會可以一并交流。

好了,我今天分享的內容就到這里,謝謝大家!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容