Apache Kylin 框架介紹

1. Apache Kylin 是什么?

Apache Kylin?是一個開源的分布式分析引擎,提供Hadoop之上的SQL查詢接口及多維分析(OLAP)能力以支持超大規模數據,最初由eBay Inc. 開發并貢獻至開源社區。它能在亞秒內查詢巨大的Hive表。

2. Apache Kylin框架介紹

Apache kylin 能提供低延遲(sub-second latency)的秘訣就是預計算,即針對一個星型拓撲結構的數據立方體,預計算多個維度組合的度量,然后將結果保存在hbase中,對外暴露JDBC、ODBC、Rest API的查詢接口,即可實現實時查詢。


Kylin 框架

如上圖所示,Kylin從Hadoop Hive中獲取數據,然后經過Cube Build Engine,將Hive中的數據Build成一個OLAP Cube保存在HBase中。用戶執行SQL查詢時,通過Query引擎,將SQL語句解析成OLAP Cube查詢,然后將結果返回給用戶。

3. Apache Kylin核心概念

1.表(table):This is definition of hive tables as source of cubes,在build cube 之前,必須同步在 kylin中。
2.模型(model):模型描述了一個星型模式的數據結構,它定義了一個事實表(Fact Table)和多個查找表(Lookup Table)的連接和過濾關系。
3. Cube 描述:描述一個Cube實例的定義和配置選項,包括使用了哪個數據模型、包含哪些維度和度量、如何將數據進行分區、如何處理自動合并等等。
4.Cube實例:通過Cube描述Build得到,包含一個或者多個Cube Segment。
5.分區(Partition):用戶可以在Cube描述中使用一個DATA/STRING的列作為分區的列,從而將一個Cube按照日期分割成多個segment。
6.立方體段(cube segmetn):它是立方體構建(build)后的數據載體,一個 segment 映射hbase中的一張表,立方體實例構建(build)后,會產生一個新的segment,一旦某個已經構建的立方體的原始數據發生變化,只需刷新(fresh)變化的時間段所關聯的segment即可。
7.聚合組:每一個聚合組是一個維度的子集,在內部通過組合構建cuboid。
8.作業(job):對立方體實例發出構建(build)請求后,會產生一個作業。該作業記錄了立方體實例build時的每一步任務信息。作業的狀態信息反映構建立方體實例的結果信息。如作業執行的狀態信息為RUNNING 時,表明立方體實例正在被構建;若作業狀態信息為FINISHED ,表明立方體實例構建成功;若作業狀態信息為ERROR ,表明立方體實例構建失??!

3.1 DIMENSION & MEASURE的種類

  • Mandotary:強制維度,所有cuboid必須包含的維度。
  • Hierarchy:層次關系維度,維度之間具有層次關系性,只需要保留一定層次關系的cuboid即可。
  • Derived:衍生維度,在lookup 表中,有一些維度可以通過它的主鍵衍生得到,所以這些維度將不參加cuboid的構建。
  • Count Distinct(HyperLogLog) :直接進行count distinct是很難去計算的,一個近似的算法HyperLogLog可以保持錯誤率在一個很低的范圍內。
  • Count Distinct(Precise):將基于RoaringBitMap進行計算,目前只支持int和BigInt。

3.2 Cube Action種類

  • BUILD:給定一個分區列指定的時間間隔,對Cube進行Build,創建一個新的cube Segment。
  • REFRESH:這個操作,將在一些分期周期內對cube Segment進行重新build。
  • MERGE:這個操作將合并多個cube segments。這個操作可以在構建cube時,設置為自動完成。
  • PURGE:清理一個Cube實例下的segment,但是不會刪除HBase表中的Tables。

3.3 Job狀態

*NEW:表示一個job已經被創建。
*PENDING:表示一個job已經被job Scheduler提交,等待執行資源。
*RUNNING:表示一個job正在運行。
*FINISHED:表示一個job成功完成。
*ERROR:表示一個job因為錯誤退出。
*DISCARDED:表示一個job被用戶取消。

3.4 Job執行

*RESUME:這個操作將從失敗的Job的最后一個成功點繼續執行該Job。
*DISCARD:無論工作的狀態,用戶可以結束它和釋放資源。

4. Apache Kylin Cube 的構建過程

4.1 Cube的物理模型

Cube物理模型

如上圖所示,一個常用的3維立方體,包含:時間、地點、產品。假如data cell 中存放的是產量,則我們可以根據時間、地點、產品來確定產量,同時也可以根據時間、地點來確定所有產品的總產量等。
Apache Kylin就將所有(時間、地點、產品)的各種組合實現算出來,data cell 中存放度量,其中每一種組合都稱為cuboid。估n維的數據最多有2^n個cuboid,不過Kylin通過設定維度的種類,可以減少cuboid的數目。

4.2 Cube構建算法介紹

4.2.1 逐層算法(Layer Cubing)

我們知道,一個N維的Cube,是由1個N維子立方體、N個(N-1)維子立方體、N*(N-1)/2個(N-2)維子立方體、......、N個1維子立方體和1個0維子立方體構成,總共有2^N個子立方體組成,在逐層算法中,按維度數逐層減少來計算,每個層級的計算(除了第一層,它是從原始數據聚合而來),是基于它上一層級的結果來計算的。
比如,[Group by A, B]的結果,可以基于[Group by A, B, C]的結果,通過去掉C后聚合得來的;這樣可以減少重復計算;當 0維度Cuboid計算出來的時候,整個Cube的計算也就完成了。


逐層算法

如上圖所示,展示了一個4維的Cube構建過程。
此算法的Mapper和Reducer都比較簡單。Mapper以上一層Cuboid的結果(Key-Value對)作為輸入。由于Key是由各維度值拼接在一起,從其中找出要聚合的維度,去掉它的值成新的Key,并對Value進行操作,然后把新Key和Value輸出,進而Hadoop MapReduce對所有新Key進行排序、洗牌(shuffle)、再送到Reducer處;Reducer的輸入會是一組有相同Key的Value集合,對這些Value做聚合計算,再結合Key輸出就完成了一輪計算。
每一輪的計算都是一個MapReduce任務,且串行執行; 一個N維的Cube,至少需要N次MapReduce Job。

算法優點

  • 此算法充分利用了MapReduce的能力,處理了中間復雜的排序和洗牌工作,故而算法代碼清晰簡單,易于維護;
  • 受益于Hadoop的日趨成熟,此算法對集群要求低,運行穩定;在內部維護Kylin的過程中,很少遇到在這幾步出錯的情況;即便是在Hadoop集群比較繁忙的時候,任務也能完成。

算法缺點

  • 當Cube有比較多維度的時候,所需要的MapReduce任務也相應增加;由于Hadoop的任務調度需要耗費額外資源,特別是集群較龐大的時候,反復遞交任務造成的額外開銷會相當可觀;
  • 由于Mapper不做預聚合,此算法會對Hadoop MapReduce輸出較多數據; 雖然已經使用了Combiner來減少從Mapper端到Reducer端的數據傳輸,所有數據依然需要通過Hadoop MapReduce來排序和組合才能被聚合,無形之中增加了集群的壓力;
  • 對HDFS的讀寫操作較多:由于每一層計算的輸出會用做下一層計算的輸入,這些Key-Value需要寫到HDFS上;當所有計算都完成后,Kylin還需要額外的一輪任務將這些文件轉成HBase的HFile格式,以導入到HBase中去;
  • 總體而言,該算法的效率較低,尤其是當Cube維度數較大的時候;時常有用戶問,是否能改進Cube算法,縮短時間。
4.2.2 快速Cube算法(Fast Cubing)

快速Cube算法(Fast Cubing)是麒麟團隊對新算法的一個統稱,它還被稱作“逐段”(By Segment) 或“逐塊”(By Split) 算法。

該算法的主要思想是,對Mapper所分配的數據塊,將它計算成一個完整的小Cube 段(包含所有Cuboid);每個Mapper將計算完的Cube段輸出給Reducer做合并,生成大Cube,也就是最終結果;圖2解釋了此流程。

快速Cube算法

與舊算法相比,快速算法主要有兩點不同

  • Mapper會利用內存做預聚合,算出所有組合;Mapper輸出的每個Key都是不同的,這樣會減少輸出到Hadoop MapReduce的數據量,Combiner也不再需要;
  • 一輪MapReduce便會完成所有層次的計算,減少Hadoop任務的調配。

子立方體生成樹的遍歷
值得一提的還有一個改動,就是子立方體生成樹(Cuboid Spanning Tree)的遍歷次序;在舊算法中,Kylin按照層級,也就是廣度優先遍歷(Broad First Search)的次序計算出各個Cuboid;在快速Cube算法中,Mapper會按深度優先遍歷(Depth First Search)來計算各個Cuboid。深度優先遍歷是一個遞歸方法,將父Cuboid壓棧以計算子Cuboid,直到沒有子Cuboid需要計算時才出棧并輸出給Hadoop;最多需要暫存N個Cuboid,N是Cube維度數。
采用DFS,是為了兼顧CPU和內存:

  • 從父Cuboid計算子Cuboid,避免重復計算;
  • 只壓棧當前計算的Cuboid的父Cuboid,減少內存占用。


    立方體生成數的遍歷過程

上圖是一個四維Cube的完整生成樹;按照DFS的次序,在0維Cuboid 輸出前的計算次序是 ABCD -> BCD -> CD -> D -> , ABCD, BCD, CD和D需要被暫存;在被輸出后,D可被輸出,內存得到釋放;在C被計算并輸出后,CD就可以被輸出; ABCD最后被輸出。

4.3 Cube構建流程

Cube構建流程

主要步驟如下:

  1. 構建一個中間平表(Hive Table):將Model中的fact表和look up表構建成一個大的Flat Hive Table。
  2. 重新分配Flat Hive Tables。
  3. 從事實表中抽取維度的Distinct值。
  4. 對所有維度表進行壓縮編碼,生成維度字典。
  5. 計算和統計所有的維度組合,并保存,其中,每一種維度組合,稱為一個Cuboid。
  6. 創建HTable。
  7. 構建最基礎的Cuboid數據。
  8. 利用算法構建N維到0維的Cuboid數據。
  9. 構建Cube。
  10. 將Cuboid數據轉換成HFile。
  11. 將HFile直接加載到HBase Table中。
  12. 更新Cube信息。
  13. 清理Hive。

5. Apache Kylin Cube 的存儲

簡單的說Cuboid的維度會映射為HBase的Rowkey,Cuboid的指標會映射為HBase的Value。


Cube映射成HBase存儲

如上圖原始表所示:Hive表有兩個維度列year和city,有一個指標列price。如上圖預聚合表所示:我們具體要計算的是year和city這兩個維度所有維度組合(即4個cuboid)下的sum(priece)指標,這個指標的具體計算過程就是由MapReduce完成的。
如上圖字典編碼所示:為了節省存儲資源,Kylin對維度值進行了字典編碼。圖中將beijing和shanghai依次編碼為0和1。

如上圖HBase KV存儲所示:在計算cuboid過程中,會將Hive表的數據轉化為HBase的KV形式。Rowkey的具體格式是cuboid id + 具體的維度值(最新的Rowkey中為了并發查詢還加入了ShardKey),以預聚合表內容的第2行為例,其維度組合是(year,city),所以cuboid id就是00000011,cuboid是8位,具體維度值是1994和shanghai,所以編碼后的維度值對應上圖的字典編碼也是11,所以HBase的Rowkey就是0000001111,對應的HBase Value就是sum(priece)的具體值

6. Apache Kylin 如何將SQL轉換成HBase Scan查詢

還是以上面的例子進行解釋,假
設查詢SQL如下:


SQL 轉換成 SCAN

這個SQL涉及維度year和city,所以其對應的cuboid是00000011,又因為city的值是確定的beijing,所以在Scan HBase時就會Scan Rowkey以00000011開頭且city的值是beijing的行,取到對應指標sum(price)的值,返回給用戶。

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

推薦閱讀更多精彩內容